談?wù)勎覍?duì)JavaScript中typeof和instanceof的深入理解
這次主要說(shuō)說(shuō)javascript的類型判斷函數(shù)typeof和判斷構(gòu)造函數(shù)原型instanceof的用法和注意的地方。
typeof
先來(lái)說(shuō)說(shuō)typeof吧。首先需要注意的是,typeof方法返回一個(gè)字符串,來(lái)表示數(shù)據(jù)的類型。
typeof 是一個(gè)一元運(yùn)算,放在一個(gè)運(yùn)算數(shù)之前,運(yùn)算數(shù)可以是任意類型。
它返回值是一個(gè)字符串,該字符串說(shuō)明運(yùn)算數(shù)的類型。typeof 一般只能返回如下幾個(gè)結(jié)果:
number,boolean,string,function,object,undefined。我們可以使用 typeof 來(lái)獲取一個(gè)變量是否存在,如 if(typeof a!="undefined"){alert("ok")},而不要去使用 if(a) 因?yàn)槿绻?a 不存在(未聲明)則會(huì)出錯(cuò),對(duì)于 Array,Null 等特殊對(duì)象使用 typeof 一律返回 object,這正是 typeof 的局限性。
語(yǔ)法講解
我們先看看各個(gè)數(shù)據(jù)類型對(duì)應(yīng)typeof的值:
數(shù)據(jù)類型 | Type |
---|---|
Undefined | “undefined” |
Null | “object” |
布爾值 | “boolean” |
數(shù)值 | “number” |
字符串 | “string” |
Symbol (ECMAScript 6 新增) | “symbol” |
宿主對(duì)象(JS環(huán)境提供的,比如瀏覽器) | Implementation-dependent |
函數(shù)對(duì)象 | “function” |
任何其他對(duì)象 | “object” |
再看看具體的實(shí)例:
// Numbers typeof 37 === 'number'; typeof 3.14 === 'number'; typeof Math.LN2 === 'number'; typeof Infinity === 'number'; typeof NaN === 'number'; // 盡管NaN是"Not-A-Number"的縮寫,意思是"不是一個(gè)數(shù)字" typeof Number(1) === 'number'; // 不要這樣使用! // Strings typeof "" === 'string'; typeof "bla" === 'string'; typeof (typeof 1) === 'string'; // typeof返回的肯定是一個(gè)字符串 typeof String("abc") === 'string'; // 不要這樣使用! // Booleans typeof true === 'boolean'; typeof false === 'boolean'; typeof Boolean(true) === 'boolean'; // 不要這樣使用! // Symbols typeof Symbol() === 'symbol'; typeof Symbol('foo') === 'symbol'; typeof Symbol.iterator === 'symbol'; // Undefined typeof undefined === 'undefined'; typeof blabla === 'undefined'; // 一個(gè)未定義的變量,或者一個(gè)定義了卻未賦初值的變量 // Objects typeof {a:1} === 'object'; // 使用Array.isArray或者Object.prototype.toString.call方法可以從基本的對(duì)象中區(qū)分出數(shù)組類型 typeof [1, 2, 4] === 'object'; typeof new Date() === 'object'; // 下面的容易令人迷惑,不要這樣使用! typeof new Boolean(true) === 'object'; typeof new Number(1) ==== 'object'; typeof new String("abc") === 'object'; // 函數(shù) typeof function(){} === 'function'; typeof Math.sin === 'function';
我們會(huì)發(fā)現(xiàn)一個(gè)問(wèn)題,就是typeof來(lái)判斷數(shù)據(jù)類型其實(shí)并不準(zhǔn)確。比如數(shù)組、正則、日期、對(duì)象的typeof返回值都是object,這就會(huì)造成一些誤差。
所以在typeof判斷類型的基礎(chǔ)上,我們還需要利用Object.prototype.toString方法來(lái)進(jìn)一步判斷數(shù)據(jù)類型。
我們來(lái)看看在相同數(shù)據(jù)類型的情況下,toString方法和typeof方法返回值的區(qū)別:
數(shù)據(jù) | toString | typeof |
---|---|---|
“foo” | String | string |
new String(“foo”) | String | object |
new Number(1.2) | Number | object |
true | Boolean | boolean |
new Boolean(true) | Boolean | object |
new Date() | Date | object |
new Error() | Error | object |
new Array(1, 2, 3) | Array | object |
/abc/g | RegExp | object |
new RegExp(“meow”) | RegExp | object |
可以看到利用toString方法可以正確區(qū)分出Array、Error、RegExp、Date等類型。
所以我們一般通過(guò)該方法來(lái)進(jìn)行數(shù)據(jù)類型的驗(yàn)證
真題檢測(cè)
但是既然今天說(shuō)到了typeof,那這里就列出幾道題目,來(lái)看看自己是否真正掌握了typeof的用法。
第一題:
var y = 1, x = y = typeof x; x;
第二題:
(function f(f){ return typeof f(); })(function(){ return 1; });
第三題:
var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0](); })(foo.bar);
第四題:
var foo = { bar: function(){ return this.baz; }, baz: 1 } typeof (f = foo.bar)();
第五題:
var f = (function f(){ return "1"; }, function g(){ return 2; })(); typeof f;
第六題:
var x = 1; if (function f(){}) { x += typeof f; } x;
第七題:
(function(foo){ return typeof foo.bar; })({ foo: { bar: 1 } });
下面公布答案了,這七題的答案分別是:
"undefined","number","undefined","undefined","number","1undefined","undefined"
做對(duì)了幾道呢?是不是很大的困惑呢?這幾題雖然都有typeof,但是考察了很多javascript的基礎(chǔ)噢。下面我們來(lái)一一詳解。
第一題:
var y = 1, x = y = typeof x; x;//"undefined"
表達(dá)式是從右往左的,x由于變量提升,類型不是null,而是undefined,所以x=y=”undefined”。
變量提升我在這篇文章中提到過(guò),可以看看。
第二題:
(function f(f){ return typeof f();//"number" })(function(){ return 1; });
傳入的參數(shù)為f也就是function(){ return 1; }這個(gè)函數(shù)。通過(guò)f()執(zhí)行后,得到結(jié)果1,所以typeof 1返回”number”。這道題很簡(jiǎn)單,主要是區(qū)分f和f()。
第三題:
var foo = { bar: function() { return this.baz; }, baz: 1 }; (function(){ return typeof arguments[0]();//"undefined" })(foo.bar);
這一題考察的是this的指向。this永遠(yuǎn)指向函數(shù)執(zhí)行時(shí)的上下文,而不是定義時(shí)的(ES6的箭頭函數(shù)不算)。當(dāng)arguments執(zhí)行時(shí),this已經(jīng)指向了window對(duì)象。所以是”undefined”。對(duì)this執(zhí)行不熟悉的同學(xué)可以看看這篇文章:深入理解this,對(duì)剛剛提到的箭頭函數(shù)感興趣的同學(xué)可以看看初步探究ES6之箭頭函數(shù)。
第四題:
var foo = { bar: function(){ return this.baz; }, baz: 1 } typeof (f = foo.bar)();//undefined
如果上面那一題做對(duì)了,那么這一題也應(yīng)該不會(huì)錯(cuò),同樣是this的指向問(wèn)題。
第五題:
var f = (function f(){ return "1"; }, function g(){ return 2; })(); typeof f;//"number"
這一題比較容易錯(cuò),因?yàn)槲以谟龅竭@道題之前也從來(lái)沒(méi)有遇到過(guò)javascript的分組選擇符。什么叫做分組選擇符呢?舉一個(gè)例子就會(huì)明白了:
var a = (1,2,3); document.write(a);//3,會(huì)以最后一個(gè)為準(zhǔn)
所以上面的題目會(huì)返回2,typeof 2當(dāng)然是”number”啦。
第六題:
var x = 1; if (function f(){}) { x += typeof f; } x;//"1undefined"
這是一個(gè)javascript語(yǔ)言規(guī)范上的問(wèn)題,在條件判斷中加入函數(shù)聲明。這個(gè)聲明語(yǔ)句本身沒(méi)有錯(cuò),也會(huì)返回true,但是javascript引擎在搜索的時(shí)候卻找不到該函數(shù)。所以結(jié)果為”1undefined”。
第七題:
(function(foo){ return typeof foo.bar; })({ foo: { bar: 1 } });
這題其實(shí)是一個(gè)考察心細(xì)程度的題目。形參的foo指向的是{ foo: { bar: 1 } }這個(gè)整體。相信這么說(shuō)就明白了。
好啦。上面的題目都是很好的資源噢。
instanceof
接下來(lái)該說(shuō)說(shuō)instanceof方法了。instanceof運(yùn)算符可以用來(lái)判斷某個(gè)構(gòu)造函數(shù)的prototype屬性是否存在于另外一個(gè)要檢測(cè)對(duì)象的原型鏈上。
instanceof 用于判斷一個(gè)變量是否某個(gè)對(duì)象的實(shí)例,如 var a=new Array();alert(a instanceof Array); 會(huì)返回 true,同時(shí) alert(a instanceof Object) 也會(huì)返回 true;這是因?yàn)?Array 是 object 的子類。再如:function test(){};var a=new test();alert(a instanceof test) 會(huì)返回
談到 instanceof 我們要多插入一個(gè)問(wèn)題,就是 function 的 arguments,我們大家也許都認(rèn)為 arguments 是一個(gè) Array,但如果使用 instaceof 去測(cè)試會(huì)發(fā)現(xiàn) arguments 不是一個(gè) Array 對(duì)象,盡管看起來(lái)很像。
如果對(duì)原型不太了解,可以看看深入理解原型。
下面我們看看instanceof的實(shí)例:
// 定義構(gòu)造函數(shù) function C(){} function D(){} var o = new C(); // true,因?yàn)?Object.getPrototypeOf(o) === C.prototype o instanceof C; // false,因?yàn)?D.prototype不在o的原型鏈上 o instanceof D; o instanceof Object; // true,因?yàn)镺bject.prototype.isPrototypeOf(o)返回true C.prototype instanceof Object // true,同上 C.prototype = {}; var o2 = new C(); o2 instanceof C; // true o instanceof C; // false,C.prototype指向了一個(gè)空對(duì)象,這個(gè)空對(duì)象不在o的原型鏈上. D.prototype = new C(); // 繼承 var o3 = new D(); o3 instanceof D; // true o3 instanceof C; // true
但是這里我們需要注意一個(gè)問(wèn)題:
function f(){ return f; } document.write(new f() instanceof f);//false function g(){} document.write(new g() instanceof g);//true
第一個(gè)為什么返回false呢?因?yàn)闃?gòu)造函數(shù)的原型被覆蓋了,我們可以看看new f和new g的區(qū)別:
- 菜鳥也能搞懂js中typeof與instanceof區(qū)別
- 詳解JavaScript中typeof與instanceof用法
- Javascript typeof與instanceof的區(qū)別
- JavaScript類型檢測(cè)之typeof 和 instanceof 的缺陷與優(yōu)化
- 淺談javascript中的instanceof和typeof
- JavaScript中instanceof與typeof運(yùn)算符的用法及區(qū)別詳細(xì)解析
- JS中typeof與instanceof之間的區(qū)別總結(jié)
- 關(guān)于js typeof 與 instanceof 判斷數(shù)據(jù)類型區(qū)別及開發(fā)使用
相關(guān)文章
JavaScript知識(shí)點(diǎn)總結(jié)(五)之Javascript中兩個(gè)等于號(hào)(==)和三個(gè)等于號(hào)(===)的區(qū)別
這篇文章主要介紹了JavaScript知識(shí)點(diǎn)總結(jié)(五)之Javascript中兩個(gè)等于號(hào)(==)和三個(gè)等于號(hào)(===)的區(qū)別的相關(guān)資料,需要的朋友可以參考下2016-05-05JavaScript不同場(chǎng)景下的文件下載方案詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript中不同場(chǎng)景下的三種常見文件下載方案,文中的示例代碼講解詳細(xì),有需要的小伙伴可以參考一下2023-12-12js實(shí)現(xiàn)web調(diào)用攝像頭 js截取視頻畫面
這篇文章主要為大家詳細(xì)介紹了JS web調(diào)用攝像頭,截取視頻畫面,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-04-04layui表單提交到后臺(tái)自動(dòng)封裝到實(shí)體類的方法
今天小編就為大家分享一篇layui表單提交到后臺(tái)自動(dòng)封裝到實(shí)體類的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09使用JavaScript檢測(cè)Firefox瀏覽器是否啟用了Firebug的代碼
在啟用Firebug的情況下訪問(wèn)GMail會(huì)收到一個(gè) Firebug會(huì)讓Gmail變慢 的警告,這是如何檢測(cè)的呢?這里就說(shuō)說(shuō)。2010-12-12