字節(jié):如何模擬實(shí)現(xiàn) new 操作符
new 運(yùn)算符創(chuàng)建一個(gè)用戶定義的對(duì)象類型的實(shí)例或具有構(gòu)造函數(shù)的內(nèi)置對(duì)象的實(shí)例。new 關(guān)鍵字會(huì)進(jìn)行如下的操作:
創(chuàng)建一個(gè)空的簡(jiǎn)單JavaScript對(duì)象(即 {});鏈接該對(duì)象(即設(shè)置該對(duì)象的構(gòu)造函數(shù))到另一個(gè)對(duì)象 ; 將步驟1新創(chuàng)建的對(duì)象作為 this的上下文 ;如果該函數(shù)沒有返回對(duì)象,則返回 this。
代碼實(shí)現(xiàn):
function new_object() {
// 創(chuàng)建一個(gè)空的對(duì)象
let obj = new Object()
// 獲得構(gòu)造函數(shù)
let Con = [].shift.call(arguments)
// 鏈接到原型 (不推薦使用)
obj.__proto__ = Con.prototype
// 綁定 this,執(zhí)行構(gòu)造函數(shù)
let result = Con.apply(obj, arguments)
// 確保 new 出來(lái)的是個(gè)對(duì)象
return typeof result === 'object' ? result : obj
}
警告: 通過現(xiàn)代瀏覽器的操作屬性的便利性,可以改變一個(gè)對(duì)象的
[[Prototype]]屬性, 這種行為在每一個(gè)JavaScript引擎和瀏覽器中都是一個(gè)非常慢且影響性能的操作,使用這種方式來(lái)改變和繼承屬性是對(duì)性能影響非常嚴(yán)重的,并且性能消耗的時(shí)間也不是簡(jiǎn)單的花費(fèi)在obj.__proto__ = ...語(yǔ)句上, 它還會(huì)影響到所有繼承來(lái)自該[[Prototype]]的對(duì)象,如果你關(guān)心性能,你就不應(yīng)該在一個(gè)對(duì)象中修改它的 [[Prototype]]。相反, 創(chuàng)建一個(gè)新的且可以繼承[[Prototype]]的對(duì)象,推薦使用Object.create()—MDN
所以進(jìn)一步優(yōu)化 new 實(shí)現(xiàn):
// 優(yōu)化后 new 實(shí)現(xiàn)
function create() {
// 1、獲得構(gòu)造函數(shù),同時(shí)刪除 arguments 中第一個(gè)參數(shù)
Con = [].shift.call(arguments);
// 2、創(chuàng)建一個(gè)空的對(duì)象并鏈接到原型,obj 可以訪問構(gòu)造函數(shù)原型中的屬性
let obj = Object.create(Con.prototype);
// 3、綁定 this 實(shí)現(xiàn)繼承,obj 可以訪問到構(gòu)造函數(shù)中的屬性
let ret = Con.apply(obj, arguments);
// 4、優(yōu)先返回構(gòu)造函數(shù)返回的對(duì)象
return ret instanceof Object ? ret : obj;
};
來(lái)自:https://github.com/sisterAn/JavaScript-Algorithms
最后
評(píng)論
圖片
表情
