方法說明javascript
new
運算符會建立一個用戶自定義對象類型(就是自定義函數、或者說構造函數)的實例或具備構造函數的內置對象(好比:Number、String等原生對象)的實例,具體的過程以下:java
建立一個空對象,
{}
閉包
- 將第一步的空對象連接到另外一個對象(
new
操做符後面跟着的構造函數的原型對象)- 將第一步建立的對象做爲構造函數的
this
上下文- 返回對象實例,若是構造函數有返回對象,則對象實例就是構造函數返回的對象,不然就返回
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"}