溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

JavaScript中instanceof 運(yùn)算符的作用是什么

發(fā)布時(shí)間:2021-06-17 16:25:11 來源:億速云 閱讀:345 作者:Leah 欄目:web開發(fā)

這篇文章給大家介紹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 運(yùn)算符的作用是什么

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ò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(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)容。

AI