new和instanceof的內部機制

白牙青森發表於2013-07-04

首先我們來看看var obj = new O()這條語句發生了什麼:

var obj = (function(){
    var obj = {};
    obj.__proto__ = O.prototype;

    //其他賦值語句...

    return obj;
})();

也就是說var obj = new O()返回了一個obj物件,它的隱式原型鏈(__proto__)是指向O原型(prototype)的。這就是new的內部工作方式。

下面再看instanceof,假設現在有 x instanceof y 一條語句,則其內部實際作出瞭如下的判斷:

while(x.__proto__!==null) {
  if(x.__proto__===y.prototype) {
    return true;
    break;
  }
  x.__proto__
= x.__proto__.proto__; }
if(x.__proto__==null) {return false;}

x會一直沿著隱式原型鏈__proto__向上查詢直到x.__proto__.__proto__......===y.prototype為止,如果找到則返回true,也就是x為y的一個例項。否則返回false,x不是y的例項。

下面舉出兩個例子,把對O的原型(prototype)的修改放在obj的宣告之前和之後的兩種情況下,使用instanceof對obj作檢測的結果對比:

 1 function F(){}
 2 function O(){}
 3 
 4 O.prototype = new F();
 5 var obj = new O();
 6 /*
    以上兩條語句等同於如下程式碼
    var obj = (function(){
      var obj1 = {};
      var obj2 = {};
      obj2.__proto__ = F.prototype;
      obj.__proto__ = obj2;
      return obj;
    })()
  */ 7 console.log(obj instanceof O);//true 8 console.log(obj instanceof F);//true 9 console.log(obj.__proto__===O.prototype);//true 10 console.log(obj.__proto__.__proto__===F.prototype);//true

上面這個例子中obj.__proto__和o.prototype都是指向new F()這個物件的,所以obj instanceof o結果為true;

假設上面new F()這個物件為objF,則根據new的內部機制,objF.__proto__===F.prototype,而objF.__proto__等於obj.__proto__.__proto__。

所以obj instanceof F結果也是true。

 1 function F(){}
 2 function O(){}
 3 
 4 var obj = new O();
 5 o.prototype = new F();
 6 
 7 console.log(obj instanceof O);//false
 8 console.log(obj instanceof F);//false
 9 console.log(obj.__proto__===O.prototype);//false
10 console.log(obj.__proto__.__proto__===F.prototype);//false

也假設上面new F()這個物件為objF。

這個例子中obj.prototype的修改在obj的宣告之後,也就是說obj.__proto__是指向o最初始的prototype,自然地obj.__proto__也與objF不相等。所以obj instanceof O結果為false。

最後,obj instance F為false也很好理解,這是因為obj.__proto__.__proto__指向的是Object.prototype。

相關文章