來自:https://zswfx.com/articles/5db9285f9cf7c10e840e5c6a
我們經常用new來創建一個對象,但是創建對象過程中,到底發生了什麼呢?
new 操作符的過程
上面是mdn的定義。
通過上面定義,我們知道使用new的時候,JS引擎就會給我們創建一個空對象作爲 this
值,然後執行函數,若函數沒有返回值,則默認返回這個空對象。
模擬 new 函數來創建對象。
根據上面mdn定義new過程,我們來模擬一下new的過程,只有模擬後,我們就知道使用new後,引擎是如何操作的,咦下面例子爲例:
function Person(name, age) {
this.name = name;
this.age = age;
}
很簡單一個例子,創建一個人。
創建一個空對象並鏈接到傳入對象中
function mockNew(...args) {
const Constructor = args[0];
const object = Object.create(Constructor.prototype);
}
在這裏,通過 Object.create 創建新對象,並把新對象 __proto__
指向傳入對象的 prototype
.
Object.create 查看這裏
把新對象作爲上下文注入
function mockNew(...args) {
const Constructor = args[0];
const object = Object.create(Constructor.prototype);
const params = args.slice(1);
Constructor.apply(object, params);
}
通過 apply
函數,將object當成 this
傳入。
返回判斷
function mockNew(...args) {
const Constructor = args[0];
const object = Object.create(Constructor.prototype);
const params = args.slice(1);
const ret = Constructor.apply(object, params);
return ret || object;
}
判斷結果,並返回。
跑一下例子
function Person(name, age) {
this.name = name;
this.age = age;
}
const pe = mockNew(Person, '戰三', 23)
console.log(pe);
通過對比,發現一抹一樣。我們就模擬的整個new
的過程。
規範上過程
es有規範,規範位於 11.2.2 new 運算符, new
屬於左值表達式(代表數值位於=號的左側)
這是在規範過程,在規範中分爲兩個情況,有參數情況和無參數情況,空參數情況按照NewExpression: new NewExpression
的左值表達式方式執行,執行的事函數無參數情況,有參數則是按照 MemberExpression: new MemberExpression Arguments
方式執行,都有關於異常處理情況,不同的是第二種會去獲取函數參數列表,並傳入[[Construct]]
內。
NewExpression: new NewExpression
和MemberExpression: new MemberExpression Arguments
均是左值表達式
總結
直接用mdn上的描述吧:
創建一個對象類型,需要創建一個指定其名稱和屬性的函數;對象的屬性可以指向其他對象,看下面的例子:
當代碼 new Foo(...) 執行時,會發生以下事情:
- 一個繼承自 Foo.prototype 的新對象被創建。
- 使用指定的參數調用構造函數 Foo,並將 this 綁定到新創建的對象。new Foo 等同於 new Foo(),也就是沒有指定參數列表,Foo 不帶任何參數調用的情況。
- 由構造函數返回的對象就是 new 表達式的結果。如果構造函數沒有顯式返回一個對象,則使用步驟1創建的對象。(一般情況下,構造函數不返回值,但是用戶可以選擇主動返回對象,來覆蓋正常的對象創建步驟)