new&instanceof原理解析及模擬實現

Jarva發表於2019-02-25

模擬實現new

需滿足:

  1. 繫結this
  2. 新建一個物件
  3. 將物件連結到原型
  4. 返回新的物件
    /**
    * 因為new是關鍵字,所以不能直接覆蓋。
    * 我們這邊用create來模擬實現。
    */

    function create () {
    let obj = {}
    let Con = [].shift.call(arguments)
    // 連結原型,使得新建物件可以訪問到建構函式原型上的屬性
    obj.__proto__ = Con.prototype
    // 繫結this
    Con.apply(obj, arguments)
    return obj
    }
複製程式碼

建構函式返回值有如下三種情況:

  • 1、有 return ,返回一個物件,例項只能訪問返回物件中的例項
  • 2、沒有 return ,即返回 undefined,例項只能訪問到建構函式中的屬性,和情況1完全相反。
  • 3、返回 undefined 以外的基本型別,等於沒有返回,例項只能訪問到建構函式中的屬性,和情況1完全相反。

綜上,所以需要判斷下返回的值是不是一個物件,如果是物件則返回這個物件,不然返回新建立的 obj物件。

    /**
    * 因為new是關鍵字,所以不能直接覆蓋。
    * 我們這邊用create來模擬實現。
    */

    function create () {
    let obj = {}
    let Con = [].shift.call(arguments)
    // 連結原型,使得新建物件可以訪問到建構函式原型上的屬性
    obj.__proto__ = Con.prototype
    // 繫結this
    let ret = Con.apply(obj, arguments)
    return ret instanceof Object ? ret : obj
    }
複製程式碼
// 測試用例
    function Car(color) {
        this.color = color;
    }
    Car.prototype.start = function() {
        console.log(this.color + " car start");
    }

    var car = create(Car, "black");
    car.color;
    // black

    car.start();
    // black car start
複製程式碼

模擬實現instanceof

instanceof 運算子用來檢測 constructor.prototype 是否存在於引數 object 的原型鏈上。

    function instanceof1 (left, right) {
        // 獲取型別原型
        let prototype = right.prototype
        // 獲取物件原型
        left = left.__proto__
        // 判斷物件的型別是否等於型別的原型
        while (true) {
            if (left === null)
                return false
            if (left === prototype)
                return true
            left = left.__proto__
        }
    }
複製程式碼

收工~

相關文章