javascript instanceof 內(nèi)部機(jī)制探析
更新時(shí)間:2010年10月15日 23:52:06 作者:
在 JavaScript 中,可以用 instanceof 來判斷一個(gè)對象是不是某個(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è)對象是某個(gè)類的實(shí)例時(shí),意味著這個(gè)對象具有該類的方法和屬性。在 JavaScript 中,一個(gè)豬類的特性體現(xiàn)在原型中:
// 代碼 3
function Pig() {}
Pig.prototype = {
"吃豬食": function() {},
"睡覺": function() {},
"長膘": 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對象或函數(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 了呢?
當(dāng)一個(gè)對象是某個(gè)類的實(shí)例時(shí),意味著這個(gè)對象具有該類的方法和屬性。在 JavaScript 中,一個(gè)豬類的特性體現(xiàn)在原型中:
復(fù)制代碼 代碼如下:
// 代碼 3
function Pig() {}
Pig.prototype = {
"吃豬食": function() {},
"睡覺": function() {},
"長膘": 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對象或函數(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實(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對于不同的構(gòu)造器或許都返回true
- 談?wù)勎覍avaScript中typeof和instanceof的深入理解
- JavaScript中instanceof運(yùn)算符的使用示例
相關(guān)文章
JavaScript中DOM和BOM的區(qū)別與用處詳解
這篇文章主要介紹了JavaScript中DOM和BOM的區(qū)別與用處,DOM和BOM是前端開發(fā)中常用的兩個(gè)概念,它們分別表示不同的對象模型,用于操作瀏覽器的不同部分,了解它們的區(qū)別和用處,有助于在前端開發(fā)中靈活使用?JavaScript?操作頁面和瀏覽器,需要的朋友可以參考下2024-09-09
淺談JavaScript構(gòu)造樹形結(jié)構(gòu)的一種高效算法
這篇文章主要介紹了JavaScript構(gòu)造樹形結(jié)構(gòu)的一種高效算法,對算法感興趣的同學(xué),可以參考下2021-05-05
配置Grunt的Task時(shí)通配符支持和動(dòng)態(tài)生成文件名問題
這篇文章主要介紹了配置Grunt的Task時(shí)通配符支持和動(dòng)態(tài)生成文件名問題,需要的朋友可以參考下2015-09-09
JavaScript幾種形式的樹結(jié)構(gòu)菜單
今天我主要講3種不同展示的JavaScript樹結(jié)構(gòu)菜單,分別是懸浮層樹(Tree)、右鍵菜單樹(ContextMenu)和節(jié)點(diǎn)樹(TreeMenu),目前都支持無限級層次。2010-05-05
關(guān)于JavaScript的gzip靜態(tài)壓縮方法
關(guān)于JavaScript的gzip靜態(tài)壓縮方法...2007-01-01
Javascript自定義排序 node運(yùn)行 實(shí)例
Javascript自定義排序 node運(yùn)行 實(shí)例,需要的朋友可以參考一下2013-06-06
js動(dòng)態(tài)調(diào)用css屬性的小規(guī)律及實(shí)例說明
本篇文章主要介紹了js動(dòng)態(tài)調(diào)用css屬性的小規(guī)律及實(shí)例說明。需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12
JavaScript惰性求值的一種實(shí)現(xiàn)方法示例
這篇文章主要給大家介紹了關(guān)于JavaScript惰性求值的一種實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-01-01

