欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript instanceof 內(nèi)部機(jī)制探析

 更新時(shí)間:2010年10月15日 23:52:06   作者:  
在 JavaScript 中,可以用 instanceof 來判斷一個(gè)對(duì)象是不是某個(gè)類或其子類的實(shí)例。
比如:
復(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?

相關(guān)文章

最新評(píng)論