mdn關(guān)于new運(yùn)算符的介紹:
new 運(yùn)算符創(chuàng)建一個(gè)自定義對象或具有構(gòu)造函數(shù)的內(nèi)置對象的實(shí)例。
是不是看著有點(diǎn)懵,那我們用實(shí)例來看看new運(yùn)算符到底做了什么鸵贬;
第一版:
function Person(name){
this.name = name
}
Person.prototype.say = function(){
console.log(`i'm ${this.name}`)
}
let student = new Person('小明')
console.log(student.name) // 小明
student.say() // i'm 小明
這里我們可以看出 通過new 創(chuàng)建的實(shí)例 student 可以訪問 Person的 屬性以及Person 定義在原型鏈上的方法脚线;
那么開始實(shí)現(xiàn):
function newObj(obj, ...args) {
// 創(chuàng)建一個(gè)空對象
let newObj = new Object()
// 將newObj的this指向obj
obj.apply(newObj, args)
// 將newObj的原型指向構(gòu)造函數(shù)的prototype
newObj.__proto__ = obj.prototype
// 返回
return newObj
}
function Person(name) {
this.name = name
}
Person.prototype.say = function () {
console.log(`i'm ${this.name}`)
}
// 測試一下
let a = newObj(Person, '小花')
console.log(a.name) // 小花
a.say() // i'm 小花
這里我們實(shí)現(xiàn)了new的基本功能,測試通過例隆。
- 如果構(gòu)造函數(shù)有返回值:
- 返回一個(gè)基本類型
function Person(name) {
this.name = name
return '小白'
}
Person.prototype.say = function () {
console.log(`i'm ${this.name}`)
}
let student = new Person('小明')
console.log(student.name) // 小明
student.say() // i'm 小明
這里可以看出當(dāng)返回值為基本類型時(shí)甥捺,并沒有什么區(qū)別,返回的還是內(nèi)部創(chuàng)建的對象镀层;
- 返回值是一個(gè)對象
function Person(name) {
this.name = name
return {Teacher:'小白'}
}
Person.prototype.say = function () {
console.log(`i'm ${this.name}`)
}
let student = new Person('小明')
console.log(student) // {Teacher:'小白'}
console.log(student.name) // undefined
這里我們可以看出镰禾,當(dāng)構(gòu)造函數(shù)內(nèi)部返回一個(gè)對象時(shí);函數(shù)內(nèi)部的對象會直接覆蓋我們內(nèi)部創(chuàng)建的那個(gè)函數(shù)。
[mdn]如果構(gòu)造函數(shù)返回了一個(gè)“對象”吴侦,那么這個(gè)對象會取代整個(gè)new出來的結(jié)果屋休。如果構(gòu)造函數(shù)沒有返回對象,那么new出來的結(jié)果為步驟1創(chuàng)建的對象备韧。(一般情況下構(gòu)造函數(shù)不返回任何值劫樟,不過用戶如果想覆蓋這個(gè)返回值,可以自己選擇返回一個(gè)普通對象來覆蓋织堂。當(dāng)然叠艳,返回?cái)?shù)組也會覆蓋,因?yàn)閿?shù)組也是對象易阳。
- 繼續(xù)實(shí)現(xiàn):
function newObj(obj, ...args) {
// 創(chuàng)建一個(gè)空對象
let newObj = new Object()
// 將newObj的原型指向構(gòu)造函數(shù)的prototype
newObj.__proto__ = obj.prototype
// 將newObj的this指向obj
let ret = obj.apply(newObj, args)
// 判斷返回值 如果返回值為對象就返回這個(gè)對象 返回值不為對象 就返回創(chuàng)建的對象
return typeof ret === 'object' ? ret : newObj
}