手寫實現JS中的new
⚠ 預備知識:
- 瞭解原型和原型鏈
- 瞭解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()為例,當它執行時,會發生以下事情:
創建一個空的簡單JS對象
const obj = {}
給這個對象添加屬性__proto__,
並將該屬性鏈接到構造函數的原型對象
obj.__proto__ = Person.prototype
調用構造函數Person
,並將this
綁定到新創建的對象obj
Person.apply(obj)
如果構造函數沒有顯式返回一個對象,則返回新創建的對象,即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 補充
ES5
提供瞭Object.create
方法,該方法可以創建一個對象,並讓新對象的__proto__
屬性指向已經存在的對象。
所以我們可以使用這個方法合並1、2兩步
const obj = Object.create(constructor.prototype) // 等價於 const obj = {} obj.__proto__ = constructor.prototype
對於第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
註意:模擬實現的函數_new傳入的參數隻能是構造函數,不能是類
class Animal { ...}_new(Animal)// 會報錯:Class constructor Animal cannot be invoked without 'new'// 類隻能通過new來創建
到此這篇關於手寫實現JS中的new的文章就介紹到這瞭,更多相關JS中的new內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- JS中的六種繼承方式以及優缺點總結
- 一文徹底理解js原生語法prototype,__proto__和constructor
- Javascript 原型與原型鏈深入詳解
- Javascript的原型和原型鏈你瞭解嗎
- JavaScript中的this例題實戰總結詳析