您好,登錄后才能下訂單哦!
這篇文章給大家介紹JavaScript中instanceof 運(yùn)算符的作用是什么,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
instanceof 運(yùn)算符簡介
在 JavaScript 中,判斷一個(gè)變量的類型嘗嘗會(huì)用 typeof 運(yùn)算符,在使用 typeof 運(yùn)算符時(shí)采用引用類型存儲(chǔ)值會(huì)出現(xiàn)一個(gè)問題,無論引用的是什么類型的對(duì)象,它都返回 "object"。ECMAScript 引入了另一個(gè) Java 運(yùn)算符 instanceof 來解決這個(gè)問題。instanceof 運(yùn)算符與 typeof 運(yùn)算符相似,用于識(shí)別正在處理的對(duì)象的類型。與 typeof 方法不同的是,instanceof 方法要求開發(fā)者明確地確認(rèn)對(duì)象為某特定類型。例如:
清單 1. instanceof 示例
var oStringObject = new String("hello world"); console.log(oStringObject instanceof String); // 輸出 "true"
這段代碼問的是“變量 oStringObject 是否為 String 對(duì)象的實(shí)例?”oStringObject 的確是 String 對(duì)象的實(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ī)制。
詳細(xì)剖析 ECMAScript-262 edition 3 中 instanceof 運(yùn)算符的定義
語言規(guī)范對(duì)中 instanceof 運(yùn)算符的定義如下:
清單 5. 規(guī)范中 instanceof 運(yùn)算符定義
11.8.6 The instanceof operator The production RelationalExpression: RelationalExpression instanceof ShiftExpression is evaluated as follows: 1. Evaluate RelationalExpression. 2. Call GetValue(Result(1)).// 調(diào)用 GetValue 方法得到 Result(1) 的值,設(shè)為 Result(2) 3. Evaluate ShiftExpression. 4. Call GetValue(Result(3)).// 同理,這里設(shè)為 Result(4) 5. If Result(4) is not an object, throw a TypeError exception.// 如果 Result(4) 不是 object, //拋出異常 /* 如果 Result(4) 沒有 [[HasInstance]] 方法,拋出異常。規(guī)范中的所有 [[...]] 方法或者屬性都是內(nèi)部的, 在 JavaScript 中不能直接使用。并且規(guī)范中說明,只有 Function 對(duì)象實(shí)現(xiàn)了 [[HasInstance]] 方法。 所以這里可以簡單的理解為:如果 Result(4) 不是 Function 對(duì)象,拋出異常 */ 6. If Result(4) does not have a [[HasInstance]] method, throw a TypeError exception. // 相當(dāng)于這樣調(diào)用:Result(4).[[HasInstance]](Result(2)) 7. Call the [[HasInstance]] method of Result(4) with parameter Result(2). 8. Return Result(7). // 相關(guān)的 HasInstance 方法定義 15.3.5.3 [[HasInstance]] (V) Assume F is a Function object.// 這里 F 就是上面的 Result(4),V 是 Result(2) When the [[HasInstance]] method of F is called with value V, the following steps are taken: 1. If V is not an object, return false.// 如果 V 不是 object,直接返回 false 2. Call the [[Get]] method of F with property name "prototype".// 用 [[Get]] 方法取 // F 的 prototype 屬性 3. Let O be Result(2).//O = F.[[Get]]("prototype") 4. If O is not an object, throw a TypeError exception. 5. Let V be the value of the [[Prototype]] property of V.//V = V.[[Prototype]] 6. If V is null, return false. // 這里是關(guān)鍵,如果 O 和 V 引用的是同一個(gè)對(duì)象,則返回 true;否則,到 Step 8 返回 Step 5 繼續(xù)循環(huán) 7. If O and V refer to the same object or if they refer to objects joined to each other (section 13.1.2), return true. 8. Go to step 5.
上面的規(guī)范定義很晦澀,而且看起來比較復(fù)雜,涉及到很多概念,但把這段規(guī)范翻譯成 JavaScript 代碼卻很簡單,如下:
清單 6. 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__; } }
JavaScript 原型繼承機(jī)制
由于本文主要集中在剖析 JavaScript instanceof 運(yùn)算符,所以對(duì)于 JavaScript 的原型繼承機(jī)制不再做詳細(xì)的講解,下面參考來自 http://www.mollypages.org/misc/js.mp 的一張圖片,此圖片詳細(xì)的描述了 JavaScript 各種對(duì)象的顯示和隱式原型鏈結(jié)構(gòu)。
由其本文涉及顯示原型和隱式原型,所以下面對(duì)這兩個(gè)概念作一下簡單說明。在 JavaScript 原型繼承結(jié)構(gòu)里面,規(guī)范中用 [[Prototype]] 表示對(duì)象隱式的原型,在 JavaScript 中用 __proto__ 表示,并且在 Firefox 和 Chrome 瀏覽器中是可以訪問得到這個(gè)屬性的,但是 IE 下不行。
所有 JavaScript 對(duì)象都有 __proto__ 屬性,但只有 Object.prototype.__proto__ 為 null,前提是沒有在 Firefox 或者 Chrome 下修改過這個(gè)屬性。這個(gè)屬性指向它的原型對(duì)象。 至于顯示的原型,在 JavaScript 里用 prototype 屬性表示,這個(gè)是 JavaScript 原型繼承的基礎(chǔ)知識(shí),在這里就不在敘述了。
JavaScript 原型鏈
講解 instanceof 復(fù)雜用法
有了上面 instanceof 運(yùn)算符的 JavaScript 代碼和原型繼承圖,再來理解 instanceof 運(yùn)算符將易如反掌。下面將詳細(xì)講解 Object instanceof Object,F(xiàn)unction instanceof Function 和 Foo instanceof Foo 三個(gè)示例,其它示例讀者可自行推演。
清單 7. 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
清單 8. 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
清單 9. 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 為例。
清單 10. 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í),會(huì)返回 false。所以 Dojo 為每個(gè)類的實(shí)例添加了一個(gè)新的方法叫 isInstanceOf,用這個(gè)方法來檢查多重繼承。
關(guān)于JavaScript中instanceof 運(yùn)算符的作用是什么就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。