欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入聊一聊JS中new的原理與實現(xiàn)

 更新時間:2021年11月03日 10:02:53   作者:JaylenL  
這篇文章主要給大家介紹了關于JS中new的原理與實現(xiàn)的相關資料,本文通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

定義

new 運算符創(chuàng)建一個用戶定義的對象類型的實例或具有構(gòu)造函數(shù)的內(nèi)置對象的實例。

使用new [constructor]的方式來創(chuàng)建一個對象實例,但構(gòu)造函數(shù)的差異會導致創(chuàng)建的實例不同。

構(gòu)造函數(shù)體不同

構(gòu)造函數(shù)也是函數(shù),其唯一的區(qū)別就是調(diào)用方式不同,任何函數(shù)只要使用 new 操作符調(diào)用就是構(gòu)造函數(shù),而不使用 new 操作符調(diào)用的函數(shù)就是普通函數(shù)。

因此構(gòu)造函數(shù)也可以帶有返回值,但是這會導致new的結(jié)果不同。

無返回值

function Person(name) {
  this.name = name;
}

let obj = new Person("Jalenl");
console.log(obj);

顯然,打印的是{name:'Jalenl'}

返回對象

function Person(age) {
  this.age = age;
  return { name: "Jalenl" };
}

let obj = new Person(18);
console.log(obj);

打印的是{name:'Jalenl'},也就是說return之前的定義都被覆蓋了。這里return的是一個對象,那返回的是個基本類型呢?

返回非對象

function Person(age) {
  this.age = age;
  return 1;
}

let obj = new Person(18);
console.log(obj);

返回{age:21},這么說return失效了,跟沒有return一樣的結(jié)果,那如果沒有this綁定內(nèi)部屬性,再返回基本數(shù)據(jù)類型呢?

沒有屬性綁定+返回非對象

function Person(){
    return 1
}
new Person()

返回的是一個空對象{},意料之中。

綜上,只有構(gòu)造函數(shù)return返回的是一個對象類型時,才能改變初始結(jié)果。

構(gòu)造函數(shù)類型不同

構(gòu)造函數(shù)為普通函數(shù)

ECMA-262 3rd. Edition Specification中的說明了對象實例的創(chuàng)建過程:

13.2.2 [[Construct]]
When the [[Construct]] property for a Function object F is called, the following steps are taken:

  1. Create a new native ECMAScript object.
  2. Set the [[Class]] property of Result(1) to "Object".
  3. Get the value of the prototype property of F.
  4. If Result(3) is an object, set the [[Prototype]] property of Result(1) to Result(3).
  5. If Result(3) is not an object, set the [[Prototype]] property of Result(1) to the original Object prototype object as described in 15.2.3.1.
  6. Invoke the [[Call]] property of F, providing Result(1) as the this value and providing the argument list passed into [[Construct]] as the argument values.
  7. If Type(Result(6)) is Object then return Result(6).
  8. Return Result(1).

總結(jié)下來就是:

  1. 在內(nèi)存中創(chuàng)建一個新對象。
  2. 這個新對象內(nèi)部的[[Prototype]]特性被賦值為構(gòu)造函數(shù)的 prototype 屬性。
  3. 構(gòu)造函數(shù)內(nèi)部的 this 被賦值為這個新對象(即 this 指向新對象)。
  4. 執(zhí)行構(gòu)造函數(shù)內(nèi)部的代碼(給新對象添加屬性)。
  5. 如果構(gòu)造函數(shù)返回對象,則返回該對象;否則,返回剛創(chuàng)建的新對象(空對象)。

第五步就已經(jīng)說明了構(gòu)造函數(shù)不同導致new結(jié)果不同的原因。

以下摘自MDN的解釋:

當代碼 new Foo(…) 執(zhí)行時,會發(fā)生以下事情:

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

構(gòu)造函數(shù)為箭頭函數(shù)

普通函數(shù)創(chuàng)建時,引擎會按照特定的規(guī)則為這個函數(shù)創(chuàng)建一個prototype屬性(指向原型對象)。默認情況下,所有原型對象自動獲得一個名為 constructor 的屬性,指回與之關聯(lián)的構(gòu)造函數(shù)。

function Person(){
    this.age = 18;
}
Person.prototype
/**
{
    constructor: ƒ Foo()
    __proto__: Object
}
**/

創(chuàng)建箭頭函數(shù)時,引擎不會為其創(chuàng)建prototype屬性,箭頭函數(shù)沒有constructor供new調(diào)用,因此使用new調(diào)用箭頭函數(shù)會報錯!

const Person = ()=>{}
new Person()//TypeError: Foo is not a constructor

手寫new

綜上,熟悉了new的工作原理后,我們可以自己實現(xiàn)一個低配版的new,實現(xiàn)的關鍵是:

  1. 讓實例可以訪問到私有屬性;
  2. 讓實例可以訪問構(gòu)造函數(shù)原型(constructor.prototype)所在原型鏈上的屬性;
  3. 構(gòu)造函數(shù)返回的最后結(jié)果是引用數(shù)據(jù)類型。
function _new(constructor, ...args) {
    // 構(gòu)造函數(shù)類型合法判斷
    if(typeof constructor !== 'function') {
      throw new Error('constructor must be a function');
    }
    // 新建空對象實例
    let obj = new Object();
    // 將構(gòu)造函數(shù)的原型綁定到新創(chuàng)的對象實例上
    obj.__proto__ = Object.create(constructor.prototype);
    // 調(diào)用構(gòu)造函數(shù)并判斷返回值
    let res = constructor.apply(obj,  args);
    let isObject = typeof res === 'object' && res !== null;
    let isFunction = typeof res === 'function';
    // 如果有返回值且返回值是對象類型,那么就將它作為返回值,否則就返回之前新建的對象
    return isObject || isFunction ? res : obj;
};

這個低配版new實現(xiàn)可以用來創(chuàng)建自定義類的實例,但不支持內(nèi)置對象,畢竟new屬于操作符,底層實現(xiàn)更加復雜。

總結(jié)

到此這篇關于JS中new的原理與實現(xiàn)的文章就介紹到這了,更多相關JS中new原理與實現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論