javascript instanceof 內(nèi)部機(jī)制探析
更新時(shí)間:2010年10月15日 23:52:06 作者:
在 JavaScript 中,可以用 instanceof 來判斷一個(gè)對(duì)象是不是某個(gè)類或其子類的實(shí)例。
比如:
// 代碼 1
function Pig() {}
var pig = new Pig();
alert(pig instanceof Pig); // => true
function FlyPig() {}
FlyPig.prototype = new Pig();
var flyPig = new FlyPig();
alert(flyPig instanceof Pig); // => true
來看另一段代碼:
// 代碼 2
function Pig() { Pig.prototype = {/* some code */} }
var pig = new Pig();
alert(pig instanceof Pig); // => false
為何上面的豬 pig 不再是豬 Pig 了呢?
當(dāng)一個(gè)對(duì)象是某個(gè)類的實(shí)例時(shí),意味著這個(gè)對(duì)象具有該類的方法和屬性。在 JavaScript 中,一個(gè)豬類的特性體現(xiàn)在原型中:
// 代碼 3
function Pig() {}
Pig.prototype = {
"吃豬食": function() {},
"睡覺": function() {},
"長(zhǎng)膘": function() {}
};
var pig = new Pig();
alert(pig instanceof Pig); //=> true
如果動(dòng)態(tài)改變了豬的特性,讓豬變成了牛:
// 代碼 4
Pig.prototype = {
"吃草": function() {},
"犁田": function() {}
};
var niu= new Pig();
alert(pig instanceof Pig); //=> false
alert(niu instanceof Pig); //=> true
當(dāng)未改變 Pig 的 prototype 時(shí),豬還是豬,因此代碼 3 中 pig 是 Pig 的實(shí)例。當(dāng)改變 prototype 后,豬已經(jīng)不是豬,而是披著豬皮的牛了。因此代碼 4 中 pig 不再是 Pig 的實(shí)例,niu 反而是 Pig 的實(shí)例。
進(jìn)一步分析前,先回顧一下 new 的內(nèi)部機(jī)制。代碼 2 中的 new Pig() 實(shí)際上等價(jià)為:
// var pig = new Pig() 的等價(jià)偽代碼:
var pig = (function() {
var o = {};
o.__proto__ = Pig.prototype; // line 2
Pig.call(o);
Pig.prototype = {/* some code */}; // line 4
return o; // line 5
})();
可以看出,在 line 2 時(shí),o.__proto__ 指向了 Pig.prototype 指向的值。但在 line 4 時(shí),Pig.prototype 指向了新值。也就是說,在 line 5 返回時(shí),pig.__proto__ !== Pig.prototype. 正是這個(gè)變化,導(dǎo)致了代碼 2 中的 pig 不是 Pig.
已經(jīng)可以大膽推論出:instanceof 判斷 pig 是不是 Pig 的依據(jù)是:看隱藏的 pig.__proto__ 屬性是否等于 Pig.prototype !
為了進(jìn)一步確認(rèn),我們可以在 Firefox 下模擬 instanceof 的內(nèi)部實(shí)現(xiàn)代碼:
/**
* Gecko 引擎下,模擬 instanceof
*/
function _instanceof(obj, cls) {
// instanceof 的左操作數(shù)必須是非null對(duì)象或函數(shù)對(duì)象
if((typeof obj !== "object" || obj === null)
&& typeof obj !== "function") {
return false;
}
// instanceof 的右操作數(shù)必須是函數(shù)對(duì)象
if(typeof cls !== "function") {
throw new Error("invalid instanceof operand (" + cls + ")");
}
// 向上回溯判斷
var p = obj.__proto__, cp = cls.prototype;
while(p) {
if(p === cp) return true;
p = p.__proto__;
}
return false;
}
測(cè)試頁(yè)面:simulate-intanceof.html
最后考考大家:
function Bird() {}
var bird = new Bird();
var o = {};
bird.__proto__ = o;
Bird.prototype = o;
alert(bird instanceof Bird); // true or false?
復(fù)制代碼 代碼如下:
// 代碼 1
function Pig() {}
var pig = new Pig();
alert(pig instanceof Pig); // => true
function FlyPig() {}
FlyPig.prototype = new Pig();
var flyPig = new FlyPig();
alert(flyPig instanceof Pig); // => true
來看另一段代碼:
復(fù)制代碼 代碼如下:
// 代碼 2
function Pig() { Pig.prototype = {/* some code */} }
var pig = new Pig();
alert(pig instanceof Pig); // => false
為何上面的豬 pig 不再是豬 Pig 了呢?
當(dāng)一個(gè)對(duì)象是某個(gè)類的實(shí)例時(shí),意味著這個(gè)對(duì)象具有該類的方法和屬性。在 JavaScript 中,一個(gè)豬類的特性體現(xiàn)在原型中:
復(fù)制代碼 代碼如下:
// 代碼 3
function Pig() {}
Pig.prototype = {
"吃豬食": function() {},
"睡覺": function() {},
"長(zhǎng)膘": function() {}
};
var pig = new Pig();
alert(pig instanceof Pig); //=> true
如果動(dòng)態(tài)改變了豬的特性,讓豬變成了牛:
復(fù)制代碼 代碼如下:
// 代碼 4
Pig.prototype = {
"吃草": function() {},
"犁田": function() {}
};
var niu= new Pig();
alert(pig instanceof Pig); //=> false
alert(niu instanceof Pig); //=> true
當(dāng)未改變 Pig 的 prototype 時(shí),豬還是豬,因此代碼 3 中 pig 是 Pig 的實(shí)例。當(dāng)改變 prototype 后,豬已經(jīng)不是豬,而是披著豬皮的牛了。因此代碼 4 中 pig 不再是 Pig 的實(shí)例,niu 反而是 Pig 的實(shí)例。
進(jìn)一步分析前,先回顧一下 new 的內(nèi)部機(jī)制。代碼 2 中的 new Pig() 實(shí)際上等價(jià)為:
復(fù)制代碼 代碼如下:
// var pig = new Pig() 的等價(jià)偽代碼:
var pig = (function() {
var o = {};
o.__proto__ = Pig.prototype; // line 2
Pig.call(o);
Pig.prototype = {/* some code */}; // line 4
return o; // line 5
})();
可以看出,在 line 2 時(shí),o.__proto__ 指向了 Pig.prototype 指向的值。但在 line 4 時(shí),Pig.prototype 指向了新值。也就是說,在 line 5 返回時(shí),pig.__proto__ !== Pig.prototype. 正是這個(gè)變化,導(dǎo)致了代碼 2 中的 pig 不是 Pig.
已經(jīng)可以大膽推論出:instanceof 判斷 pig 是不是 Pig 的依據(jù)是:看隱藏的 pig.__proto__ 屬性是否等于 Pig.prototype !
為了進(jìn)一步確認(rèn),我們可以在 Firefox 下模擬 instanceof 的內(nèi)部實(shí)現(xiàn)代碼:
復(fù)制代碼 代碼如下:
/**
* Gecko 引擎下,模擬 instanceof
*/
function _instanceof(obj, cls) {
// instanceof 的左操作數(shù)必須是非null對(duì)象或函數(shù)對(duì)象
if((typeof obj !== "object" || obj === null)
&& typeof obj !== "function") {
return false;
}
// instanceof 的右操作數(shù)必須是函數(shù)對(duì)象
if(typeof cls !== "function") {
throw new Error("invalid instanceof operand (" + cls + ")");
}
// 向上回溯判斷
var p = obj.__proto__, cp = cls.prototype;
while(p) {
if(p === cp) return true;
p = p.__proto__;
}
return false;
}
測(cè)試頁(yè)面:simulate-intanceof.html
最后考考大家:
復(fù)制代碼 代碼如下:
function Bird() {}
var bird = new Bird();
var o = {};
bird.__proto__ = o;
Bird.prototype = o;
alert(bird instanceof Bird); // true or false?
您可能感興趣的文章:
- javascript instanceof,typeof的區(qū)別
- JS中typeof與instanceof之間的區(qū)別總結(jié)
- JavaScript constructor和instanceof,JSOO中的一對(duì)歡喜冤家
- 理解Javascript_07_理解instanceof實(shí)現(xiàn)原理
- JavaScript中instanceof與typeof運(yùn)算符的用法及區(qū)別詳細(xì)解析
- javascript instanceof 與typeof使用說明
- 關(guān)于javascript中的typeof和instanceof介紹
- JavaScript中instanceof運(yùn)算符的用法總結(jié)
- javascript之typeof、instanceof操作符使用探討
- JavaScript instanceof 的使用方法示例介紹
- 解析JavaScript中instanceof對(duì)于不同的構(gòu)造器或許都返回true
- 談?wù)勎覍?duì)JavaScript中typeof和instanceof的深入理解
- JavaScript中instanceof運(yùn)算符的使用示例
相關(guān)文章
Bootstrap作品展示站點(diǎn)實(shí)戰(zhàn)項(xiàng)目2
這篇文章主要為大家分享了Bootstrap作品展示站點(diǎn)實(shí)戰(zhàn)項(xiàng)目,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-10-10javascript實(shí)現(xiàn)鼠標(biāo)放上后下邊對(duì)應(yīng)內(nèi)容變換的效果
這篇文章主要介紹了javascript鼠標(biāo)放上后下邊對(duì)應(yīng)內(nèi)容變換的方法,實(shí)例分析了javascript實(shí)現(xiàn)tab切換的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08JavaScript實(shí)現(xiàn)英語(yǔ)單詞題庫(kù)
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)英語(yǔ)單詞題庫(kù),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12js導(dǎo)入導(dǎo)出excel(實(shí)例代碼)
這篇文章主要是對(duì)js導(dǎo)入導(dǎo)出excel的實(shí)例代碼進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對(duì)大家有所幫助2013-11-11django admin 使用SimpleUI自定義按鈕彈窗框示例
Django 后臺(tái)admin有大量的屬性和方法,擁有強(qiáng)大的功能和自定義能力,這篇文章主要介紹了django admin 使用SimpleUI自定義按鈕彈窗框示例,需要的朋友可以參考下2023-04-04JS獲取字符串實(shí)際長(zhǎng)度(包含漢字)的簡(jiǎn)單方法
下面小編就為大家?guī)硪黄狫S獲取字符串實(shí)際長(zhǎng)度(包含漢字)的簡(jiǎn)單方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-08-08