DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> javascript instanceof 內部機制探析
javascript instanceof 內部機制探析
編輯:關於JavaScript     
比如:
復制代碼 代碼如下:
// 代碼 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 中,一個豬類的特性體現在原型中:
復制代碼 代碼如下:
// 代碼 3
function Pig() {}
Pig.prototype = {
"吃豬食": function() {},
"睡覺": function() {},
"長膘": function() {}
};
var pig = new Pig();
alert(pig instanceof Pig); //=> true

如果動態改變了豬的特性,讓豬變成了牛:
復制代碼 代碼如下:
// 代碼 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 後,豬已經不是豬,而是披著豬皮的牛了。因此代碼 4 中 pig 不再是 Pig 的實例,niu 反而是 Pig 的實例。

進一步分析前,先回顧一下 new 的內部機制。代碼 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. 正是這個變化,導致了代碼 2 中的 pig 不是 Pig.

已經可以大膽推論出:instanceof 判斷 pig 是不是 Pig 的依據是:看隱藏的 pig.__proto__ 屬性是否等於 Pig.prototype !

為了進一步確認,我們可以在 Firefox 下模擬 instanceof 的內部實現代碼:
復制代碼 代碼如下:
/**
* Gecko 引擎下,模擬 instanceof
*/
function _instanceof(obj, cls) {
// instanceof 的左操作數必須是非null對象或函數對象
if((typeof obj !== "object" || obj === null)
&& typeof obj !== "function") {
return false;
}

// instanceof 的右操作數必須是函數對象
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?
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved