先看一個(gè)例子:
function Foo(){
}
Foo.prototype.constructor === Foo//true
var obj = new Foo()
obj.constructor === Foo//true
函數(shù)的prototype對(duì)象上有一個(gè)constructor屬性,這個(gè)屬性的默認(rèn)值是當(dāng)前函數(shù)蝶防。至于obj對(duì)象為什么能夠訪(fǎng)問(wèn)到constructor的話(huà),那就得回顧之前提到的對(duì)象的[[Prototype]]的知識(shí)了慧脱。因?yàn)閛bj的[[Prototype]]屬性指向的值是Foo函數(shù),所以當(dāng)在obj自身上找不到某個(gè)屬性時(shí)菱鸥,就會(huì)在其原型鏈上進(jìn)行查找躏鱼。
1.構(gòu)造函數(shù)與普通調(diào)用的混搭
一個(gè)函數(shù)是否是構(gòu)造函數(shù)與其寫(xiě)法沒(méi)關(guān)系。與調(diào)用方式才有關(guān)系染苛。
- 如果我們?cè)谄胀ǖ暮瘮?shù)調(diào)用前面加上new關(guān)鍵字之后鹊漠,就會(huì)把這個(gè)函數(shù)調(diào)用變成一個(gè)構(gòu)造函數(shù)調(diào)用,如果之前那個(gè)函數(shù)沒(méi)有return的話(huà)登钥,那么變成構(gòu)造函數(shù)之后返回一個(gè){}娶靡,并且返回的這個(gè)對(duì)象的[[Prototype]]屬性會(huì)指向普通函數(shù)的prototype對(duì)象:
function fun(){
console.log("?")
}
var obj = new fun()
console.log(obj)//fun {}
console.log(Object.getPrototypeOf(obj) === fun.prototype)//true
利用這個(gè)特性,我們可以共享數(shù)據(jù):
function fun(){}
fun.prototype.a = "haha"
var obj = new fun()
var obj2 = new fun()
console.log(obj.a)//"haha"
console.log(obj2.a)//"haha"
console.log(Object.getOwnPropertyDescriptor(fun.prototype, "a"))//"writable":true...
obj.a = "self"
console.log(obj.a)//"self"
console.log(obj2.a)//"haha"
- 如果我們?cè)谄胀ǖ暮瘮?shù)調(diào)用前面加上new關(guān)鍵字之后姿锭,就會(huì)把這個(gè)函數(shù)調(diào)用變成一個(gè)構(gòu)造函數(shù)調(diào)用,如果之前的那個(gè)函數(shù)是return一個(gè)對(duì)象的話(huà)轮纫,那么變成構(gòu)造函數(shù)之后返回的內(nèi)容不會(huì)發(fā)生改變焚鲜。但是返回的這個(gè)對(duì)象并不會(huì)被普通函數(shù)的prototype對(duì)象所委托,而是被Object.prototype所委托糯彬。所以此時(shí)new相當(dāng)于沒(méi)用任何作用:
funtion foo(){
return {"w": 9}
}
var obj = new foo()
console.log(obj)//{"w": 9}
console.log(Object.getOwnPrototypeOf(obj) == Object.prototype)//true
- 如果一個(gè)普通函數(shù)具有return語(yǔ)句贝乎,但是return的內(nèi)容是非對(duì)象的話(huà)览效,那么如果在這個(gè)普通函數(shù)之前加上new關(guān)鍵詞的話(huà),就會(huì)把這個(gè)函數(shù)調(diào)用變成一個(gè)構(gòu)造函數(shù)調(diào)用锤灿。此時(shí)返回一個(gè)空對(duì)象辆脸,并且返回的這個(gè)空對(duì)象會(huì)被函數(shù)的prototype對(duì)象所委托:
function foo(){
return 1
}
var obj = new foo()
console.log(obj)//foo {}
console.log(Object.getPrototypeOf(obj) == foo.prototype)//true
值得注意的是,這里說(shuō)的非對(duì)象是哪些:比如數(shù)值状囱,字符串倘是,布爾值龙巨。哪些不行呢:比如說(shuō)數(shù)組阳似,函數(shù)旗芬。
- 如果對(duì)于一個(gè)“構(gòu)造函數(shù)”調(diào)用的時(shí)候答倡,并沒(méi)有為其添加new方式調(diào)用的話(huà)驴党,那么此時(shí)他將作為普通函數(shù)調(diào)用。此時(shí)返回的將會(huì)是undefined鼻弧。
function foo(){
this. a = 1
}
var obj = foo()
console.log(obj)//undefined
//由于是undefined,所以更別提什么會(huì)被什么對(duì)象委托的事情了叉存。
當(dāng)然度帮,如果老老實(shí)實(shí)遵循規(guī)范寫(xiě)的話(huà),上面那些狗屁東西都不會(huì)遇到瞳秽。