官术网_书友最值得收藏!

1.4.2 typeof運(yùn)算符

typeof運(yùn)算符用于返回操作數(shù)的數(shù)據(jù)類型,有以下兩種使用形式。


typeof operand
typeof (operand)

其中operand表示需要返回?cái)?shù)據(jù)類型的操作數(shù),可以是引用類型,也可以是基本數(shù)據(jù)類型。

括號(hào)有的時(shí)候是必須的,如果不加上括號(hào)將會(huì)因?yàn)閮?yōu)先級(jí)的問題得不到我們想要的結(jié)果。

typeof運(yùn)算符在處理不同數(shù)據(jù)類型時(shí)會(huì)得到不同的結(jié)果,圖1-2總結(jié)出了可能的返回值。

圖1-2

針對(duì)圖1-2中不同的數(shù)據(jù)類型,下面總結(jié)了一些使用場(chǎng)景。

1. 處理Undefined類型的值

雖然Undefined類型的值只有一個(gè)undefined,但是typeof運(yùn)算符在處理以下3種值時(shí)都會(huì)返回“undefined”。

· undefined本身。

· 未聲明的變量。

· 已聲明未初始化的變量。


var declaredButUnde?nedVariable;
typeof unde?ned === 'unde?ned';    // true
typeof declaredButUnde?nedVariable === 'unde?ned';  // true,已聲明未初始化的變量
typeof undeclaredVariable === 'unde?ned';  // true,未聲明的變量

2. 處理Boolean類型的值

Boolean類型的值只有兩個(gè),分別是true和false。typeof運(yùn)算符在處理這兩個(gè)值以及它們的包裝類型時(shí)都會(huì)返回“boolean”,但是不推薦使用包裝類型的寫法。


typeof true === 'boolean';          // true
typeof false === 'boolean';         // true
typeof Boolean(true) === 'boolean'; // true,不推薦這么寫

3. 處理Number類型的值

對(duì)于Number類型的數(shù)據(jù),可以概括為以下這些值,typeof運(yùn)算符在處理時(shí)會(huì)返回“number”。

· 數(shù)字,如1、123、145。

· Number類型的靜態(tài)變量,如Number.MAX_VALUE、Number.EPSILON等。

· Math對(duì)象的靜態(tài)變量值,如Math.PI、Math.LN2(以e為底,2的對(duì)數(shù))。

· NaN,雖然NaN是Not a Number的縮寫,但它是Number類型的值。

· Infinity和-Infinity,表示的是無窮大和無窮小的數(shù)。

· 數(shù)值類型的包裝類型,如Number(1)、Number(123),雖然它們也會(huì)返回“number”,但是并不推薦這么寫。

通過上述的總結(jié),我們可以快速完成以下這些測(cè)試。


typeof 37 === 'number';        // true
typeof 3.14 === 'number';      // true
typeof Math.LN2 === 'number';  // true
typeof In?nity === 'number';   // true
typeof NaN === 'number';       // true
typeof Number(1) === 'number'; // true,不推薦這么寫

4. 處理String類型的值

對(duì)于String類型的數(shù)據(jù),可以概括為以下這些值,typeof運(yùn)算符在處理時(shí)會(huì)返回“string”。

· 任何類型的字符串,包括空字符串和非空字符串。

· 返回值為字符串類型的表達(dá)式。

· 字符串類型的包裝類型,例如String('hello')、String('hello' + 'world'),雖然它們也會(huì)返回“String”,但是并不推薦這么寫。

通過上述的總結(jié),我們可以快速完成以下這些測(cè)試。


typeof "" === 'string';            // true
typeof "bla" === 'string';         // true
typeof (typeof 1) === 'string';    // true,因?yàn)閠ypeof會(huì)返回一個(gè)字符串
typeof String("abc") === 'string'; // true,不推薦這么寫

5. 處理Symbol類型的值

Symbol類型是在ES6中新增的原生數(shù)據(jù)類型,表示一個(gè)獨(dú)一無二的值,typeof運(yùn)算符處理后得到的返回值為“symbol”。


typeof Symbol() === 'symbol';      // true
typeof Symbol('foo') === 'symbol'; // true

6. 處理Function類型的值

對(duì)于Function類型的數(shù)據(jù),可以概括為以下這些值,typeof運(yùn)算符在處理時(shí)會(huì)返回“function”。

· 函數(shù)的定義,包括函數(shù)聲明或者函數(shù)表達(dá)式兩種形式。

· 使用class關(guān)鍵字定義的類,class是在ES6中新增的關(guān)鍵字,它不是一個(gè)全新的概念,原理依舊是原型繼承,本質(zhì)上仍然是一個(gè)Function。

· 某些內(nèi)置對(duì)象的特定函數(shù),例如Math.sin()函數(shù)、Number.isNaN()函數(shù)等。

· Function類型對(duì)象的實(shí)例,一般通過new關(guān)鍵字得到。

通過上述的總結(jié),我們可以快速完成以下這些測(cè)試。


var foo = function () {};
function foo2() {}

typeof foo === 'function';       // true,函數(shù)表達(dá)式
typeof foo2 === 'function';      // true,函數(shù)聲明
typeof class C{} === 'function'; // true
typeof Math.sin === 'function';  // true
typeof new Function() === 'function';  // true,new操作符得到Function類型的實(shí)例

7. 處理Object類型的值

對(duì)于Object類型的數(shù)據(jù),可以概括為以下這些值,typeof運(yùn)算符在處理時(shí)會(huì)返回“object”。

· 對(duì)象字面量形式,例如{name: 'kingx'}。

· 數(shù)組,例如[1, 2, 3]和Array(1, 2, 3)。

· 所有構(gòu)造函數(shù)通過new操作符實(shí)例化后得到的對(duì)象,例如new Date()、new function(){},但是new Function(){}除外。

· 通過new操作符得到的基本數(shù)據(jù)類型的包裝類型對(duì)象,如new Boolean(true)、newNumber(1),但不推薦這么寫。

細(xì)心的讀者可能發(fā)現(xiàn)了,與基本數(shù)據(jù)類型的包裝類型相關(guān)的部分,我們都有寫“不推薦這么寫”,這是為什么呢?

因?yàn)樯婕鞍b類型時(shí),使用了new操作符與沒有使用new操作符得到的值在通過typeof運(yùn)算符處理后得到的結(jié)果是不一樣的,很容易讓人混淆。

通過上述的總結(jié),我們可以快速完成以下這些測(cè)試。


typeof {a:1} === 'object';      // true,對(duì)象字面量
typeof [1, 2, 4] === 'object';  // true,數(shù)組
typeof new Date() === 'object'; // true,Date對(duì)象的實(shí)例
// 下面的代碼容易令人迷惑,不要使用!
typeof new Boolean(true) === 'object';  // true
typeof new Number(1) === 'object';      // true
typeof new String("abc") === 'object';  // true

typeof運(yùn)算符的使用在絕大部分情況下都是安全的,但是在ES6以后情況就不一樣了。這里總結(jié)了使用typeof運(yùn)算符時(shí)需要考慮的問題。

1. typeof運(yùn)算符區(qū)分對(duì)待Object類型和Function類型

在Nicholas C.Zakas所著的《JavaScript高級(jí)程序設(shè)計(jì)》一書中講到,從技術(shù)角度講,函數(shù)在ECMAScript中是對(duì)象,不是一種數(shù)據(jù)類型。然而,函數(shù)也確實(shí)有一些特殊的屬性,因此通過typeof運(yùn)算符來區(qū)分函數(shù)和其他對(duì)象是有必要的。

另外,在實(shí)際使用過程中,有必要區(qū)分Object類型和Function類型,而typeof運(yùn)算符就能幫我們實(shí)現(xiàn)。

2. typeof運(yùn)算符對(duì)null的處理

使用typeof運(yùn)算符對(duì)null進(jìn)行處理,返回的是“object”,這是一個(gè)讓大家都感到驚訝的結(jié)果。因?yàn)閚ull是一個(gè)原生類型的數(shù)據(jù),為什么typeof運(yùn)算符會(huì)返回“object”呢?

這是一個(gè)在JavaScript設(shè)計(jì)之初就存在的問題,這里簡(jiǎn)單介紹下。

在JavaScript中,每種數(shù)據(jù)類型都會(huì)使用3bit表示。

· 000表示Object類型的數(shù)據(jù)。

· 001表示Int類型的數(shù)據(jù)。

· 010表示Double類型的數(shù)據(jù)。

· 100表示String類型的數(shù)據(jù)。

· 110表示Boolean類型的數(shù)據(jù)。

由于null代表的是空指針,大多數(shù)平臺(tái)中值為0x00,因此null的類型標(biāo)簽就成了0,所以使用typeof運(yùn)算符時(shí)會(huì)判斷為object類型,返回“object”。

雖然在后面的提案中有提出修復(fù)方案,但是因?yàn)橛绊懨嫣螅圆]有被采納,從而導(dǎo)致這個(gè)問題一直存在。

3. typeof運(yùn)算符相關(guān)語法的括號(hào)

在前文中有講到,括號(hào)有時(shí)是必須存在的,如果不加上括號(hào)則會(huì)因?yàn)閮?yōu)先級(jí)的問題得不到我們想要的結(jié)果。

我們可以通過以下代碼看看加不加括號(hào)在結(jié)果上的差異。


var number = 123;
typeof (number + ' hello');  // "string"
typeof number + ' hello';    // "number hello"

因?yàn)閠ypeof運(yùn)算符的優(yōu)先級(jí)會(huì)高于字符串拼接運(yùn)算符(+),但是優(yōu)先級(jí)低于小括號(hào)(),所以在未使用括號(hào)時(shí),會(huì)優(yōu)先處理typeof number,返回的是"number",然后與"hello"字符串進(jìn)行拼接,得到結(jié)果"number hello"。

下面是更能體現(xiàn)括號(hào)重要性的例子。


typeof 1 / 0;     // "NaN"
typeof (1 / 0);   // "number"

第一行代碼中,因?yàn)闆]有小括號(hào),實(shí)際會(huì)先運(yùn)行typeof 1,返回的是"number",然后除以0,一個(gè)字符串除以0,得到的是"NaN"。

第二行代碼中,因?yàn)槭褂昧诵±ㄌ?hào),實(shí)際會(huì)先運(yùn)行1/0,得到的是Infinity,而Infinity實(shí)際上為Number類型的值,通過typeof運(yùn)算符處理后,得到的是"number"。

因此在處理某些表達(dá)式時(shí),需要將這些表達(dá)式用括號(hào)括起來以保證先運(yùn)算表達(dá)式,再使用typeof運(yùn)算符進(jìn)行運(yùn)算。

主站蜘蛛池模板: 房山区| 莫力| 定边县| 衡阳市| 农安县| 温泉县| 英超| 闻喜县| 印江| 汶川县| 建宁县| 阿拉善左旗| 蕲春县| 沂水县| 榆树市| 淳安县| 淮南市| 凤山县| 姜堰市| 襄汾县| 丘北县| 黎平县| 冷水江市| 平昌县| 陵川县| 五莲县| 井冈山市| 镇沅| 日照市| 涞水县| 垦利县| 马山县| 山东省| 时尚| 塘沽区| 大足县| 天长市| 宝应县| 湘阴县| 西和县| 黎川县|