先看一個例子:
function Foo(){
}
Foo.prototype.constructor === Foo//true
var obj = new Foo()
obj.constructor === Foo//true
函數(shù)的prototype對象上有一個constructor屬性,這個屬性的默認(rèn)值是當(dāng)前函數(shù)。至于obj對象為什么能夠訪問到constructor的話,那就得回顧之前提到的對象的[[Prototype]]的知識了。因為obj的[[Prototype]]屬性指向的值是Foo函數(shù),所以當(dāng)在obj自身上找不到某個屬性時,就會在其原型鏈上進(jìn)行查找。
1.構(gòu)造函數(shù)與普通調(diào)用的混搭
一個函數(shù)是否是構(gòu)造函數(shù)與其寫法沒關(guān)系。與調(diào)用方式才有關(guān)系。
- 如果我們在普通的函數(shù)調(diào)用前面加上new關(guān)鍵字之后,就會把這個函數(shù)調(diào)用變成一個構(gòu)造函數(shù)調(diào)用,如果之前那個函數(shù)沒有return的話,那么變成構(gòu)造函數(shù)之后返回一個{},并且返回的這個對象的[[Prototype]]屬性會指向普通函數(shù)的prototype對象:
function fun(){
console.log("?")
}
var obj = new fun()
console.log(obj)//fun {}
console.log(Object.getPrototypeOf(obj) === fun.prototype)//true
利用這個特性,我們可以共享數(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"
- 如果我們在普通的函數(shù)調(diào)用前面加上new關(guān)鍵字之后,就會把這個函數(shù)調(diào)用變成一個構(gòu)造函數(shù)調(diào)用,如果之前的那個函數(shù)是return一個對象的話,那么變成構(gòu)造函數(shù)之后返回的內(nèi)容不會發(fā)生改變。但是返回的這個對象并不會被普通函數(shù)的prototype對象所委托,而是被Object.prototype所委托。所以此時new相當(dāng)于沒用任何作用:
funtion foo(){
return {"w": 9}
}
var obj = new foo()
console.log(obj)//{"w": 9}
console.log(Object.getOwnPrototypeOf(obj) == Object.prototype)//true
- 如果一個普通函數(shù)具有return語句,但是return的內(nèi)容是非對象的話,那么如果在這個普通函數(shù)之前加上new關(guān)鍵詞的話,就會把這個函數(shù)調(diào)用變成一個構(gòu)造函數(shù)調(diào)用。此時返回一個空對象,并且返回的這個空對象會被函數(shù)的prototype對象所委托:
function foo(){
return 1
}
var obj = new foo()
console.log(obj)//foo {}
console.log(Object.getPrototypeOf(obj) == foo.prototype)//true
值得注意的是,這里說的非對象是哪些:比如數(shù)值,字符串,布爾值。哪些不行呢:比如說數(shù)組,函數(shù)。
- 如果對于一個“構(gòu)造函數(shù)”調(diào)用的時候,并沒有為其添加new方式調(diào)用的話,那么此時他將作為普通函數(shù)調(diào)用。此時返回的將會是undefined。
function foo(){
this. a = 1
}
var obj = foo()
console.log(obj)//undefined
//由于是undefined,所以更別提什么會被什么對象委托的事情了。
當(dāng)然,如果老老實實遵循規(guī)范寫的話,上面那些狗屁東西都不會遇到。