填坑十萬個為什麼?(15)

NO IMAGE

簡介:很多概念不清或忘記,重新構建自己的知識體系。每天問自己1~多個問題。我是菜鳥 成為大神之路!

1. newinstanceof的內部機制?

  • 創建一個新對象,同時繼承對象類的原型,即Person.prototype;
  • 執行對象類的構造函數,同時該實例的屬性和方法被this所引用,即this指向新構造的實例;
  • 如果構造函數return了一個新的“對象”,那麼這個對象就會取代整個new出來的結果。如果構造函數沒有return對象,那麼就會返回步驟1所創建的對象,即隱式返回this。(一般情況下構造函數不會返回任何值,不過在一些特殊情況下,如果用戶想覆蓋這個值,可以選擇返回一個普通的對象來覆蓋。)

用代碼來闡述

// let p = new Person()
let p = (function () {
    let obj = {};
    obj.__proto__ = Person.prototype;
    
    // 其他賦值語句...
    
    return obj;
})();

下面通過代碼闡述instanceof的內部機制,假設現在有x instanceof y一條語句,則其內部實際做了如下判斷:

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

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

function F() {}
function O() {}

O.prototype = new F();
var obj = new O();

console.log(obj instanceof O); // true
console.log(obj instanceof F); // true
console.log(obj.__proto__ === O.prototype); // true
console.log(obj.__proto__.__proto__ === F.prototype); // true

根據new的內部機制改寫上面代碼

function F() {}
function O() {}

var obj = (function () {
    var obj1 = {};
    obj1.__proto__ = F.prototype; // new F();
    O.prototype = obj1; // O.prototype = new F();
    obj.__proto__ = O.prototype; // new O();
    obj.__proto__ = obj1;
    return obj;
})();

結合instanceof內部機制很容易得出正確答案。
如果稍微調整一下代碼順序,結果將迥然不同

function F() {}
function O() {}

var obj = new O();
O.prototype = new F();

console.log(obj instanceof O); // false
console.log(obj instanceof F); // false
console.log(obj.__proto__ === O.prototype); // false
console.log(obj.__proto__.__proto__ === F.prototype); // false

參考文章:
騰訊前端面試篇(一)

相關文章

填坑十萬個為什麼?(19)

填坑十萬個為什麼?(18)

填坑十萬個為什麼?(17)

填坑十萬個為什麼?(16)前15天小結