new 運算符實現原理

new 運算符

方法說明javascript

new運算符會建立一個用戶自定義對象類型(就是自定義函數、或者說構造函數)的實例或具備構造函數的內置對象(好比:Number、String等原生對象)的實例,具體的過程以下:java

  1. 建立一個空對象,{}閉包

    1. 將第一步的空對象連接到另外一個對象(new操做符後面跟着的構造函數的原型對象)
    2. 將第一步建立的對象做爲構造函數的this上下文
    3. 返回對象實例,若是構造函數有返回對象,則對象實例就是構造函數返回的對象,不然就返回this做爲對象實例

劃重點函數

從上面的第3步和第4步能夠看出來,經過 new操做符建立一個對象實例時,構造函數中的 this並不必定指向建立出來實例對象,你們能夠複製如下 「示例代碼」 去測試:

示例代碼測試

// 示例一,構造函數沒有返回對象,this等於建立出來的實例對象
let obj1 = null
function E1 () {
  obj1 = this
}
const ins1 = new E1()
console.log(obj1 === ins1)  // true

// 示例二,構造函數返回了一個對象,this不等於建立出來的實例對象
let obj2 = null
function E2 () {
  obj2 = this
  return { e: 'ee' }
}
const ins2 = new E2()
console.log(obj2 === ins2)  // false

源碼點撥this

邏輯較爲簡單,重點在於理解上面的 「方法說明」 、 「劃重點」、」示例代碼「 三部份內容,源碼就是實現 「方法說明」 的一個過程,經過 閉包 + Object.create() + Function.prototype.call來實現,具體的可參考代碼中的詳細註釋

源碼prototype

const myNew = function (constructor) {
  return function (...args) {
    // 完成一、2兩步,建立一個連接到構造函數的原型對象的對象
    const obj = Object.create(constructor.prototype)
    // 將obj做爲構造函數的this上下文
    constructor.call(obj, ...args)
    // 若是構造函數有返回值,則將返回值做爲實例對象返回,不然返回obj做爲實例對象
    return constructor() || obj
  }
}

// 示例 1,構造函數無返回值
function T1 (arg1, arg2) {
  this.arg1 = arg1
  this.arg2 = arg2
}
const ins1 = myNew(T1)(1, 2)
console.log(ins1)  // {arg1: 1, arg2: 2}

// 示例 2,構造函數有返回值
function T2 (arg1, arg2) {
  this.arg1 = arg1
  this.arg2 = arg2
  return { a: 'aa' }
}
const ins2 = myNew(T2)(1, 2)
console.log(ins2)  // {a: "aa"}
相關文章
相關標籤/搜索