国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 開(kāi)發(fā) > JS > 正文

深入剖析JavaScript instanceof 運(yùn)算符

2024-05-06 16:52:10
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

instanceof 運(yùn)算符簡(jiǎn)介

在 JavaScript 中,判斷一個(gè)變量的類(lèi)型嘗嘗會(huì)用 typeof 運(yùn)算符,在使用 typeof 運(yùn)算符時(shí)采用引用類(lèi)型存儲(chǔ)值會(huì)出現(xiàn)一個(gè)問(wèn)題,無(wú)論引用的是什么類(lèi)型的對(duì)象,它都返回 "object"。ECMAScript 引入了另一個(gè) Java 運(yùn)算符 instanceof 來(lái)解決這個(gè)問(wèn)題。instanceof 運(yùn)算符與 typeof 運(yùn)算符相似,用于識(shí)別正在處理的對(duì)象的類(lèi)型。與 typeof 方法不同的是,instanceof 方法要求開(kāi)發(fā)者明確地確認(rèn)對(duì)象為某特定類(lèi)型。例如:

清單 1. instanceof 示例

var oStringObject = new String("hello world"); console.log(oStringObject instanceof String); // 輸出 "true"

這段代碼問(wèn)的是“變量 oStringObject 是否為 String 對(duì)象的實(shí)例?”oStringObject 的確是 String 對(duì)象的實(shí)例,因此結(jié)果是"true"。盡管不像 typeof 方法那樣靈活,但是在 typeof 方法返回 "object" 的情況下,instanceof 方法還是很有用的。

instanceof 運(yùn)算符的常規(guī)用法

通常來(lái)講,使用 instanceof 就是判斷一個(gè)實(shí)例是否屬于某種類(lèi)型。例如:

清單 2. instanceof 常規(guī)用法

// 判斷 foo 是否是 Foo 類(lèi)的實(shí)例function Foo(){} var foo = new Foo(); console.log(foo instanceof Foo)//true

另外,更重的一點(diǎn)是 instanceof 可以在繼承關(guān)系中用來(lái)判斷一個(gè)實(shí)例是否屬于它的父類(lèi)型。例如:

清單 3. instanceof 在繼承中關(guān)系中的用法

// 判斷 foo 是否是 Foo 類(lèi)的實(shí)例 , 并且是否是其父類(lèi)型的實(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)系中的父類(lèi),在多層繼承關(guān)系中,instanceof 運(yùn)算符同樣適用。

你真的了解 instanceof 操作符嗎?

看了上面的代碼示例,是不是覺(jué)得 instanceof 操作符很簡(jiǎn)單,下面來(lái)看點(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,而其他類(lèi) instanceof 自己卻又不等于 true 呢?如何解釋?要想從根本上了解 instanceof 的奧秘,需要從兩個(gè)方面著手:1,語(yǔ)言規(guī)范中是如何定義這個(gè)運(yùn)算符的。2,JavaScript 原型繼承機(jī)制。

詳細(xì)剖析 ECMAScript-262 edition 3 中 instanceof 運(yùn)算符的定義

語(yǔ)言規(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) 沒(méi)有 [[HasInstance]] 方法,拋出異常。規(guī)范中的所有 [[...]] 方法或者屬性都是內(nèi)部的,在 JavaScript 中不能直接使用。并且規(guī)范中說(shuō)明,只有 Function 對(duì)象實(shí)現(xiàn)了 [[HasInstance]] 方法。所以這里可以簡(jiǎn)單的理解為:如果 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ī)范定義很晦澀,而且看起來(lái)比較復(fù)雜,涉及到很多概念,但把這段規(guī)范翻譯成 JavaScript 代碼卻很簡(jiǎn)單,如下:

清單 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ì)的講解,下面參考來(lái)自 http://www.mollypages.org/misc/js.mp 的一張圖片,此圖片詳細(xì)的描述了 JavaScript 各種對(duì)象的顯示和隱式原型鏈結(jié)構(gòu)。

由其本文涉及顯示原型和隱式原型,所以下面對(duì)這兩個(gè)概念作一下簡(jiǎn)單說(shuō)明。在 JavaScript 原型繼承結(jié)構(gòu)里面,規(guī)范中用 [[Prototype]] 表示對(duì)象隱式的原型,在 JavaScript 中用 __proto__ 表示,并且在 Firefox 和 Chrome 瀏覽器中是可以訪問(wèn)得到這個(gè)屬性的,但是 IE 下不行。

所有 JavaScript 對(duì)象都有 __proto__ 屬性,但只有 Object.prototype.__proto__ 為 null,前提是沒(méi)有在 Firefox 或者 Chrome 下修改過(guò)這個(gè)屬性。這個(gè)屬性指向它的原型對(duì)象。 至于顯示的原型,在 JavaScript 里用 prototype 屬性表示,這個(gè)是 JavaScript 原型繼承的基礎(chǔ)知識(shí),在這里就不在敘述了。

JavaScript,instanceof,運(yùn)算符

JavaScript 原型鏈

講解 instanceof 復(fù)雜用法

有了上面 instanceof 運(yùn)算符的 JavaScript 代碼和原型繼承圖,再來(lái)理解 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

簡(jiǎn)析 instanceof 在 Dojo 繼承機(jī)制中的應(yīng)用

在 JavaScript 中,是沒(méi)有多重繼承這個(gè)概念的,就像 Java 一樣。但在 Dojo 中使用 declare 聲明類(lèi)時(shí),是允許繼承自多個(gè)類(lèi)的。下面以 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)算符來(lái)檢查 foo 是否是 Boo 的實(shí)例時(shí),返回的是 false。實(shí)際上,在 Dojo 的內(nèi)部,F(xiàn)oo 仍然只繼承自 Aoo,而通過(guò) mixin 機(jī)制把 Boo 類(lèi)中的方法和屬性拷貝到 Foo 中,所以當(dāng)用 instanceof 運(yùn)算符來(lái)檢查是否是 Boo 的實(shí)例時(shí),會(huì)返回 false。所以 Dojo 為每個(gè)類(lèi)的實(shí)例添加了一個(gè)新的方法叫 isInstanceOf,用這個(gè)方法來(lái)檢查多重繼承。

結(jié)束語(yǔ)

本文詳細(xì)介紹了 JavaScript 語(yǔ)言中 instanceof 運(yùn)算符,并且結(jié)合語(yǔ)言規(guī)范深入剖析了此操作符的算法。對(duì)讀者使用 JavaScript 編寫(xiě)復(fù)雜的面向?qū)ο蟪绦驎?huì)有很大的幫助。本文所有代碼在 Firefox 15 下通過(guò)測(cè)試。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持VeVb武林網(wǎng)。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JavaScript/Ajax教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 石泉县| 平度市| 砀山县| 荣成市| 广水市| 瑞丽市| 塔河县| 禹州市| 阿拉尔市| 巫山县| 怀宁县| 三河市| 武山县| 云和县| 林芝县| 奉新县| 山丹县| 邵武市| 金阳县| 抚宁县| 怀来县| 平原县| 云梦县| 修水县| 乌拉特后旗| 漳平市| 新乐市| 邻水| 华池县| 兴宁市| 竹山县| 平陆县| 武胜县| 温宿县| 永吉县| 诸暨市| 呼玛县| 内黄县| 天等县| 三明市| 礼泉县|