深入一點 - 用 new 的時候到底發生了什麼?

來自: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 NewExpressionMemberExpression: new MemberExpression Arguments 均是左值表達式

總結

直接用mdn上的描述吧:

創建一個對象類型,需要創建一個指定其名稱和屬性的函數;對象的屬性可以指向其他對象,看下面的例子:

當代碼 new Foo(...) 執行時,會發生以下事情:

  1. 一個繼承自 Foo.prototype 的新對象被創建。
  2. 使用指定的參數調用構造函數 Foo,並將 this 綁定到新創建的對象。new Foo 等同於 new Foo(),也就是沒有指定參數列表,Foo 不帶任何參數調用的情況。
  3. 由構造函數返回的對象就是 new 表達式的結果。如果構造函數沒有顯式返回一個對象,則使用步驟1創建的對象。(一般情況下,構造函數不返回值,但是用戶可以選擇主動返回對象,來覆蓋正常的對象創建步驟)

源碼地址: https://github.com/zsirfs/con...

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章