手寫js new,new的過程到底發生了什麼

板栗拌饭發表於2024-10-28

在JavaScript中,new關鍵字的應用可以說是再平常不過了,最基礎的有new Array()、new Set(),再而就是new一個自己建立的建構函式,也就是建立一個該建構函式的示例。如:var person1 = new Person("一顆蘋果", 18);但你是否真的瞭解new以及它的底層原理呢,本文將舉出幾個例子並且手寫一個 new 來帶大家深入理解。

new

new的使用方法

function Car(make, model, year) {
  this.make = make;
  this.model = model;
  this.year = year;
}

const car1 = new Car('Eagle', 'Talon TSi', 1993);

console.log(car1.make);   //輸出: "Eagle"

那麼new的過程發生了什麼呢

  • 建立一個空物件:建立一個空的簡單 JavaScript 物件。為方便起見,我們稱之為 newInstance

  • 指定原型鏈:將 newInstance 的 [[Prototype]] 指向建構函式的 prototype 屬性,否則 newInstance 將保持為一個普通物件,其 [[Prototype]] 為 Object.prototype

  • 更改this指向:使用給定引數執行建構函式,並將 newInstance 繫結為 this 的上下文。

  • 返回值:返回newInstance。

手寫一個new

function myNew(Fun, ...args) {
    let obj = {}
    obj.__proto__ = Fun.prototype
    Fun.apply(obj, args)
    return obj
}
function Person(name,age) {
    this.name = name
    this.age = age
}
let apple = myNew(Person, '一顆蘋果','18')
console.log(apple.name);   //輸出:一顆蘋果
console.log(apple.age);    //輸出:18
  • ...args:將剩下的元素都放進args

  • obj. __ proto __ = Fun.prototype:將 obj 的原型鏈指向建構函式的 prototype 屬性

  • Fun.apply(obj, args):將建構函式內部的this繫結到obj上,並執行建構函式

透過這一系列操作,我們就可以拿到建構函式中的 nameage屬性了

看似完成了,但其實落了很重要的一點

回想一下,我們透過new函式建立一個物件時,除了引用它的屬性,我們還會做些什麼呢?
let arr = new Array()
arr.push(4)
arr.unshift(3)
console.log(arr);

當然是使用它自帶的方法,但是上面並沒有給出方法上的引用。這就得引入原型鏈這個知識點了,我們只需要給Person的原型鏈上增加我們想要的方法就可以了,實現程式碼如下:

function myNew(Fun, ...args) {
    let obj = {}
    obj.__proto__ = Fun.prototype
    Fun.apply(obj, args)
    return obj
}
function Person(name,age) {
    this.name = name
    this.age = age
}
Person.prototype.who = function () {
    console.log('我是Person的例項物件');
}
Person.prototype.myname = function () {
    console.log(this.name)
}
let p = myNew(Person, '一顆蘋果')
p.who();      // 輸出:我是Person的例項物件
p.myname();   // 輸出:一顆蘋果
console.log(p.name);  // 輸出:一顆蘋果
這就是我們的最終答案了,把它交給面試官,perfect!!

相關文章