javascript instanceof 內部機制探析

來源:互聯網
上載者:User

比如: 複製代碼 代碼如下:// 代碼 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?

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.