javascript instanceof 內(nèi)部機制探析
更新時間:2010年10月15日 23:52:06 作者:
在 JavaScript 中,可以用 instanceof 來判斷一個對象是不是某個類或其子類的實例。
比如:
// 代碼 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 了呢?
當一個對象是某個類的實例時,意味著這個對象具有該類的方法和屬性。在 JavaScript 中,一個豬類的特性體現(xiàn)在原型中:
// 代碼 3
function Pig() {}
Pig.prototype = {
"吃豬食": function() {},
"睡覺": function() {},
"長膘": function() {}
};
var pig = new Pig();
alert(pig instanceof Pig); //=> true
如果動態(tài)改變了豬的特性,讓豬變成了牛:
// 代碼 4
Pig.prototype = {
"吃草": function() {},
"犁田": function() {}
};
var niu= new Pig();
alert(pig instanceof Pig); //=> false
alert(niu instanceof Pig); //=> true
當未改變 Pig 的 prototype 時,豬還是豬,因此代碼 3 中 pig 是 Pig 的實例。當改變 prototype 后,豬已經(jīng)不是豬,而是披著豬皮的牛了。因此代碼 4 中 pig 不再是 Pig 的實例,niu 反而是 Pig 的實例。
進一步分析前,先回顧一下 new 的內(nèi)部機制。代碼 2 中的 new Pig() 實際上等價為:
// var pig = new Pig() 的等價偽代碼:
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 時,o.__proto__ 指向了 Pig.prototype 指向的值。但在 line 4 時,Pig.prototype 指向了新值。也就是說,在 line 5 返回時,pig.__proto__ !== Pig.prototype. 正是這個變化,導(dǎo)致了代碼 2 中的 pig 不是 Pig.
已經(jīng)可以大膽推論出:instanceof 判斷 pig 是不是 Pig 的依據(jù)是:看隱藏的 pig.__proto__ 屬性是否等于 Pig.prototype !
為了進一步確認,我們可以在 Firefox 下模擬 instanceof 的內(nèi)部實現(xiàn)代碼:
/**
* Gecko 引擎下,模擬 instanceof
*/
function _instanceof(obj, cls) {
// instanceof 的左操作數(shù)必須是非null對象或函數(shù)對象
if((typeof obj !== "object" || obj === null)
&& typeof obj !== "function") {
return false;
}
// instanceof 的右操作數(shù)必須是函數(shù)對象
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;
}
測試頁面: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 了呢?
當一個對象是某個類的實例時,意味著這個對象具有該類的方法和屬性。在 JavaScript 中,一個豬類的特性體現(xiàn)在原型中:
復(fù)制代碼 代碼如下:
// 代碼 3
function Pig() {}
Pig.prototype = {
"吃豬食": function() {},
"睡覺": function() {},
"長膘": function() {}
};
var pig = new Pig();
alert(pig instanceof Pig); //=> true
如果動態(tài)改變了豬的特性,讓豬變成了牛:
復(fù)制代碼 代碼如下:
// 代碼 4
Pig.prototype = {
"吃草": function() {},
"犁田": function() {}
};
var niu= new Pig();
alert(pig instanceof Pig); //=> false
alert(niu instanceof Pig); //=> true
當未改變 Pig 的 prototype 時,豬還是豬,因此代碼 3 中 pig 是 Pig 的實例。當改變 prototype 后,豬已經(jīng)不是豬,而是披著豬皮的牛了。因此代碼 4 中 pig 不再是 Pig 的實例,niu 反而是 Pig 的實例。
進一步分析前,先回顧一下 new 的內(nèi)部機制。代碼 2 中的 new Pig() 實際上等價為:
復(fù)制代碼 代碼如下:
// var pig = new Pig() 的等價偽代碼:
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 時,o.__proto__ 指向了 Pig.prototype 指向的值。但在 line 4 時,Pig.prototype 指向了新值。也就是說,在 line 5 返回時,pig.__proto__ !== Pig.prototype. 正是這個變化,導(dǎo)致了代碼 2 中的 pig 不是 Pig.
已經(jīng)可以大膽推論出:instanceof 判斷 pig 是不是 Pig 的依據(jù)是:看隱藏的 pig.__proto__ 屬性是否等于 Pig.prototype !
為了進一步確認,我們可以在 Firefox 下模擬 instanceof 的內(nèi)部實現(xiàn)代碼:
復(fù)制代碼 代碼如下:
/**
* Gecko 引擎下,模擬 instanceof
*/
function _instanceof(obj, cls) {
// instanceof 的左操作數(shù)必須是非null對象或函數(shù)對象
if((typeof obj !== "object" || obj === null)
&& typeof obj !== "function") {
return false;
}
// instanceof 的右操作數(shù)必須是函數(shù)對象
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;
}
測試頁面: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中的一對歡喜冤家
- 理解Javascript_07_理解instanceof實現(xiàn)原理
- JavaScript中instanceof與typeof運算符的用法及區(qū)別詳細解析
- javascript instanceof 與typeof使用說明
- 關(guān)于javascript中的typeof和instanceof介紹
- JavaScript中instanceof運算符的用法總結(jié)
- javascript之typeof、instanceof操作符使用探討
- JavaScript instanceof 的使用方法示例介紹
- 解析JavaScript中instanceof對于不同的構(gòu)造器或許都返回true
- 談?wù)勎覍avaScript中typeof和instanceof的深入理解
- JavaScript中instanceof運算符的使用示例
相關(guān)文章
javascript實現(xiàn)鼠標放上后下邊對應(yīng)內(nèi)容變換的效果
這篇文章主要介紹了javascript鼠標放上后下邊對應(yīng)內(nèi)容變換的方法,實例分析了javascript實現(xiàn)tab切換的相關(guān)技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-08-08django admin 使用SimpleUI自定義按鈕彈窗框示例
Django 后臺admin有大量的屬性和方法,擁有強大的功能和自定義能力,這篇文章主要介紹了django admin 使用SimpleUI自定義按鈕彈窗框示例,需要的朋友可以參考下2023-04-04