1. 程式人生 > 其它 >前端面試手寫程式碼——模擬實現new運算子

前端面試手寫程式碼——模擬實現new運算子

1 new 運算子簡介 2 new 究竟幹了什麼事 3 模擬實現 new 運算子 4 補充 目錄

⚠ 預備知識:

  1. 瞭解原型和原型鏈
  2. 瞭解this繫結

1 new 運算子簡介

MDN文件:new 運算子建立一個使用者定義的物件型別的例項或具有建構函式的內建物件的例項。

class Person {
    constructor(name) {
        this.name = name;
    }
}
// 建立自定義物件型別的例項
const person = new Person('小明')
// 建立具有建構函式的內建物件的例項
const date = new Date()

new的作用:建立物件的例項

2 new 究竟幹了什麼事

上面說了new的作用是建立物件的例項,那麼它究竟是怎麼建立例項的,內部幹了哪幾件事?

new Person()為例,當它執行時,會發生以下事情:

  1. 建立一個空的簡單JS物件

    const obj = {}
    
  2. 給這個物件新增屬性__proto__,並將該屬性連結到建構函式的原型物件

    obj.__proto__ = Person.prototype
    
  3. 呼叫建構函式Person,並將this繫結到新建立的物件obj

    Person.apply(obj)
    
  4. 如果建構函式沒有顯式返回一個物件,則返回新建立的物件,即obj

3 模擬實現 new 運算子

如上所述,new

運算子就幹了這麼4件事,下面我們就根據這4個步驟用函式來模擬實現new(面試手寫程式碼)

const _new = function(constructor, ...args) {
    const obj = {}
    obj.__proto__ = constructor.prototype
    const res = constructor.apply(obj, args)
    // 這一步在"補充"中會詳細解釋
    return res instanceof Object ? res : obj
}

程式碼非常簡單,就是按照上面4步,一步一步寫就可以了

4 補充

  1. ES5

    提供了Object.create方法,該方法可以建立一個物件,並讓新物件的__proto__屬性指向已經存在的物件。

    所以我們可以使用這個方法合併1、2兩步

    const obj = Object.create(constructor.prototype)
    // 等價於
    const obj = {}
    obj.__proto__ = constructor.prototype
    
  2. 對於第4步,再解釋一下

    • 如果建構函式沒有顯式return(通常情況)

      那麼person新建立的物件obj

    • 如果建構函式返回的不是一個物件,比如1"abc"

      那麼person新建立的物件obj

      function Person() {
        ...
        return 1
      }
      
    • 如果建構函式顯式返回了一個物件,比如{}function() {}

      那麼person不是新建立的物件obj了,而是顯式return的這個物件

      function Person() {
        // 函式也是物件
        return function() {}
      }
      

    所以我們在_new函式最後一句程式碼是:

    return res instanceof Object ? res : obj
    
  3. 注意,模擬實現的函式_new傳入的引數只能是建構函式,不能是類

    class Animal {  ...}_new(Animal)// 會報錯:Class constructor Animal cannot be invoked without 'new'// 類只能通過new來建立例項
    

公眾號【前端嘛】獲取更多優質內容