1.首先創(chuàng)建了一個(gè)空對(duì)象个粱,這個(gè)對(duì)象將會(huì)作為執(zhí)行構(gòu)造函數(shù)之后返回的對(duì)象實(shí)例。
2.使上面創(chuàng)建的空對(duì)象的原型(proto)指向構(gòu)造函數(shù)的prototype屬性翻翩。
3.將這個(gè)空對(duì)象賦值給構(gòu)造函數(shù)內(nèi)部的this都许,并執(zhí)行構(gòu)造函數(shù)邏輯稻薇。
4.根據(jù)構(gòu)造函數(shù)執(zhí)行邏輯,返回第一步創(chuàng)建的對(duì)象或構(gòu)造函數(shù)的顯式返回值胶征。
因?yàn)閚ew是JavaScript的關(guān)鍵字塞椎,因此不能直接將其覆蓋,但是可以通過(guò)實(shí)現(xiàn)一個(gè)函數(shù)newFunc來(lái)進(jìn)行模擬睛低。預(yù)期對(duì)newFunc的使用方式如下:
function Person(name){
this.name=name
}
const person = new newFunc(Person,'fzs')
console.log(person)
// 輸出 {name:'fzs'}
現(xiàn)在我們來(lái)實(shí)現(xiàn)一個(gè)newFunc,代碼如下
function newFunc(...args){
// 取出args數(shù)組的第一個(gè)參數(shù)忱屑,即目標(biāo)的構(gòu)造函數(shù)
const constructor = args.shift()
//創(chuàng)建一個(gè)空對(duì)象,且使這個(gè)對(duì)象繼承構(gòu)造函數(shù)的prototype屬性
//即實(shí)現(xiàn) obj._prot_ === constructor.prototype
const obj = Object.create(constructor.prototype)
// 執(zhí)行構(gòu)造函數(shù)暇昂,得到構(gòu)造函數(shù)返回結(jié)果
// 注意,這里使用 apply 使構(gòu)造函數(shù)的 this 指向 obj
const result = constructor.apply(obj,args)
// 如果構(gòu)造函數(shù)執(zhí)行后伴嗡,返回結(jié)果是對(duì)象類(lèi)型急波,則直接將該結(jié)果返回。否則返回obj對(duì)象
return (typeof result === 'object' && result!=null)
}
上述代碼并不復(fù)雜瘪校,涉及到的幾個(gè)關(guān)鍵點(diǎn)如下:
- 使用 Object.create 使 obj 的 proto 指向構(gòu)造函數(shù)的原型澄暮。
- 使用 apply 方法使構(gòu)造函數(shù)內(nèi)的this指向 obj
- 在newFunc返回時(shí), 使用三目運(yùn)算符決定返回結(jié)果阱扬。
下面來(lái)看一下構(gòu)造函數(shù)如果有顯式返回值的時(shí)候
function Person(name){
this.name=name
return {1:1}
}
console.log(person)
看上面輸出可以知道泣懊,構(gòu)造函數(shù)如果有顯示返回值,且返回值為對(duì)象類(lèi)型的話(huà)麻惶,那么構(gòu)造函數(shù)返回結(jié)果就不再是目標(biāo)實(shí)例了馍刮。所以我們?cè)趯?shí)現(xiàn)newFunc的時(shí)候要注意下這些注意點(diǎn)
另外一個(gè)注意點(diǎn):不要使用箭頭函數(shù)來(lái)做構(gòu)造函數(shù)
因?yàn)榧^函數(shù)沒(méi)有 prototype ,也沒(méi)有this 跟 arguments對(duì)象窃蹋。所以有涉及到 this 跟 arguments 不要使用箭頭函數(shù)
另外構(gòu)造函數(shù)的原型方法需要通過(guò) this 獲得實(shí)例卡啰,因此箭頭函數(shù)不可以出現(xiàn)在構(gòu)造函數(shù)的原型方法上,下面就是錯(cuò)誤用法
// 錯(cuò)誤用法1
Person.prototype = () => {
// .....
}
// 錯(cuò)誤用法2
const person = {
name: 'fzs',
getName:() => {
console.log(this.name)
}
}
person.getName()
上述錯(cuò)誤用法2中警没,getName函數(shù)體內(nèi)的this其實(shí)是指向window匈辱,所以不符合其用意。舉一反三吧杀迹。知道以上的注意點(diǎn)之后亡脸。再去理解