實(shí)例講解JavaScript中instanceof運(yùn)算符的用法
instanceof 運(yùn)算符簡介
在 JavaScript 中,判斷一個(gè)變量的類型嘗嘗會用 typeof 運(yùn)算符,在使用 typeof 運(yùn)算符時(shí)采用引用類型存儲值會出現(xiàn)一個(gè)問題,無論引用的是什么類型的對象,它都返回 “object”。ECMAScript 引入了另一個(gè) Java 運(yùn)算符 instanceof 來解決這個(gè)問題。instanceof 運(yùn)算符與 typeof 運(yùn)算符相似,用于識別正在處理的對象的類型。與 typeof 方法不同的是,instanceof 方法要求開發(fā)者明確地確認(rèn)對象為某特定類型。例如:
清單 1. instanceof 示例
var oStringObject = new String("hello world"); console.log(oStringObject instanceof String); // 輸出 "true"
這段代碼問的是“變量 oStringObject 是否為 String 對象的實(shí)例?”oStringObject 的確是 String 對象的實(shí)例,因此結(jié)果是”true”。盡管不像 typeof 方法那樣靈活,但是在 typeof 方法返回 “object” 的情況下,instanceof 方法還是很有用的。
instanceof 運(yùn)算符的常規(guī)用法:
通常來講,使用 instanceof 就是判斷一個(gè)實(shí)例是否屬于某種類型。例如:
清單 2. instanceof 常規(guī)用法
// 判斷 foo 是否是 Foo 類的實(shí)例 function Foo(){} var foo = new Foo(); console.log(foo instanceof Foo)//true
另外,更重的一點(diǎn)是 instanceof 可以在繼承關(guān)系中用來判斷一個(gè)實(shí)例是否屬于它的父類型。例如:
清單 3. instanceof 在繼承中關(guān)系中的用法
// 判斷 foo 是否是 Foo 類的實(shí)例 , 并且是否是其父類型的實(shí)例 function Aoo(){} function Foo(){} Foo.prototype = new Aoo();//JavaScript 原型繼承 var foo = new Foo(); console.log(foo instanceof Foo)//true console.log(foo instanceof Aoo)//true
上面的代碼中是判斷了一層繼承關(guān)系中的父類,在多層繼承關(guān)系中,instanceof 運(yùn)算符同樣適用。
你真的了解 instanceof 操作符嗎?
看了上面的代碼示例,是不是覺得 instanceof 操作符很簡單,下面來看點(diǎn)復(fù)雜的用法。
清單 4. instanceof 復(fù)雜用法
console.log(Object instanceof Object);//true console.log(Function instanceof Function);//true console.log(Number instanceof Number);//false console.log(String instanceof String);//false console.log(Function instanceof Object);//true console.log(Foo instanceof Function);//true console.log(Foo instanceof Foo);//false
看了上面的代碼是不是又暈頭轉(zhuǎn)向了?為什么 Object 和 Function instanceof 自己等于 true,而其他類 instanceof 自己卻又不等于 true 呢?如何解釋?要想從根本上了解 instanceof 的奧秘,需要從兩個(gè)方面著手:1,語言規(guī)范中是如何定義這個(gè)運(yùn)算符的。2,JavaScript 原型繼承機(jī)制。
清單 5. JavaScript instanceof 運(yùn)算符代碼
function instance_of(L, R) {//L 表示左表達(dá)式,R 表示右表達(dá)式 var O = R.prototype;// 取 R 的顯示原型 L = L.__proto__;// 取 L 的隱式原型 while (true) { if (L === null) return false; if (O === L)// 這里重點(diǎn):當(dāng) O 嚴(yán)格等于 L 時(shí),返回 true return true; L = L.__proto__; } }
清單 6. Object instanceof Object
// 為了方便表述,首先區(qū)分左側(cè)表達(dá)式和右側(cè)表達(dá)式 ObjectL = Object, ObjectR = Object; // 下面根據(jù)規(guī)范逐步推演 O = ObjectR.prototype = Object.prototype L = ObjectL.__proto__ = Function.prototype // 第一次判斷 O != L // 循環(huán)查找 L 是否還有 __proto__ L = Function.prototype.__proto__ = Object.prototype // 第二次判斷 O == L // 返回 true
清單 7. Function instanceof Function
// 為了方便表述,首先區(qū)分左側(cè)表達(dá)式和右側(cè)表達(dá)式 FunctionL = Function, FunctionR = Function; // 下面根據(jù)規(guī)范逐步推演 O = FunctionR.prototype = Function.prototype L = FunctionL.__proto__ = Function.prototype // 第一次判斷 O == L // 返回 true
清單 8. Foo instanceof Foo
// 為了方便表述,首先區(qū)分左側(cè)表達(dá)式和右側(cè)表達(dá)式 FooL = Foo, FooR = Foo; // 下面根據(jù)規(guī)范逐步推演 O = FooR.prototype = Foo.prototype L = FooL.__proto__ = Function.prototype // 第一次判斷 O != L // 循環(huán)再次查找 L 是否還有 __proto__ L = Function.prototype.__proto__ = Object.prototype // 第二次判斷 O != L // 再次循環(huán)查找 L 是否還有 __proto__ L = Object.prototype.__proto__ = null // 第三次判斷 L == null // 返回 false
簡析 instanceof 在 Dojo 繼承機(jī)制中的應(yīng)用
在 JavaScript 中,是沒有多重繼承這個(gè)概念的,就像 Java 一樣。但在 Dojo 中使用 declare 聲明類時(shí),是允許繼承自多個(gè)類的。下面以 Dojo 1.6.1 為例。
清單 9. Dojo 中多重繼承
dojo.declare("Aoo",null,{}); dojo.declare("Boo",null,{}); dojo.declare("Foo",[Aoo,Boo],{}); var foo = new Foo(); console.log(foo instanceof Aoo);//true console.log(foo instanceof Boo);//false console.log(foo.isInstanceOf(Aoo));//true console.log(foo.isInstanceOf(Boo));//true
上面的示例中,F(xiàn)oo 同時(shí)繼承自 Aoo 和 Boo,但當(dāng)使用 instanceof 運(yùn)算符來檢查 foo 是否是 Boo 的實(shí)例時(shí),返回的是 false。實(shí)際上,在 Dojo 的內(nèi)部,F(xiàn)oo 仍然只繼承自 Aoo,而通過 mixin 機(jī)制把 Boo 類中的方法和屬性拷貝到 Foo 中,所以當(dāng)用 instanceof 運(yùn)算符來檢查是否是 Boo 的實(shí)例時(shí),會返回 false。所以 Dojo 為每個(gè)類的實(shí)例添加了一個(gè)新的方法叫 isInstanceOf,用這個(gè)方法來檢查多重繼承。
相關(guān)文章
深入學(xué)習(xí)JavaScript中的原型prototype
這篇文章主要介紹了深入學(xué)習(xí)JavaScript中的原型prototype,是JavaScript入門學(xué)習(xí)中的基礎(chǔ)知識,需要的朋友可以參考下2015-08-08Ruffy javascript 學(xué)習(xí)筆記
Ruffy javascript 學(xué)習(xí)筆記2009-11-11JavaScript學(xué)習(xí)筆記整理_簡單實(shí)現(xiàn)枚舉類型,撲克牌應(yīng)用
下面小編就為大家?guī)硪黄狫avaScript學(xué)習(xí)筆記整理_簡單實(shí)現(xiàn)枚舉類型,撲克牌應(yīng)用。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-09-09想學(xué)習(xí)javascript JS和jQuery哪個(gè)重要 先學(xué)哪個(gè)
在一些技術(shù)論壇與qq群經(jīng)??吹接羞@樣類似的提問,當(dāng)然提出這樣問題的通常都是新手為了解決大家的疑惑,同時(shí)幫助新手程序員能更快掌握學(xué)習(xí)的方向,不致于弄錯(cuò)重點(diǎn)2016-12-12JavaScript中setTimeout和setInterval函數(shù)的傳參及調(diào)用
這篇文章主要介紹了JavaScript中setTimeout和setInterval函數(shù)的傳參及調(diào)用,著兩個(gè)函數(shù)可以把要執(zhí)行的代碼在設(shè)定的一個(gè)時(shí)間點(diǎn)插入js引擎維護(hù)的一個(gè)代碼隊(duì)列中,需要的朋友可以參考下2016-03-03