眾所周知,在建立特殊用處的例項時,建構函式發揮了很大的作用。
而且,建構函式必須靠new表示式配合使用。
相聲中說:
三分逗,七分捧同樣,建立例項的過程中,其實發揮著更重要的作用的是new表示式。
如果沒有new表示式,建構函式和普通函式無本質區別。
就像《食神》中說的那樣:
根本就沒有什麼食神,或者說,人人都是食神。所以,歡迎走進new的世界。
如下建構函式:
function
wangjianlin()
wangjianlin.prototype.money =
'1000億'
var sicong =
newwangjianlin()
console.
log(sicong.iq)
// 180
console.
log(sicong.money)
// 1000億
/** 這段**,簡單表現了wangjianlin和sicong的三個關係:
* 1. 讓sicong出生。
* 2. 讓sicong繼承1000。
* 3. 讓sicong的iq為180。
* 4. 將sicong返還給國民。
*/
由此可以看出,建構函式用new實現了三個功能:
1.建立乙個物件。
2.讓它繼承建構函式的屬性庫。
3.將建構函式的this指標替換成它,構造它。
4.返回這個物件。
上述**new wangjianlin()
的作用,可用偽**表示為:
new
wangjianlin
=// 先天繼承:
baby.__proto__ = wangjianlin.prototype
// 後天調教:
var boy = wangjianlin.
call
(baby)
// 乙個嶄新的國民老公即將誕生!
return
typeof boy ===
'object'
? boy : baby
}
建立乙個_new函式來實現上述功能:
function
_new
(fn)
obj.__proto__ = fn.prototype
var args =
[...arguments]
.slice(1
)var newobj = fn.
call
(obj,
...args)
return
typeof newobj ===
'object'
? newobj : obj
}var sicong =
_new
(wangjianlin)
// 普通函式foo:
function
foo(
)// 建構函式animal:
function
animal
(name)
/** 1. 正常使用
* */
foo(
)var dog =
newanimal
('哈士奇'
)// dog:
/** 2. 反常使用
* */
var obj =
newfoo()
// obj: {}
animal
('哈士奇'
)console.
log(window.name)
// '哈士奇'。已經汙染了全域性。
/** 可見,所謂的普通函式可以當建構函式來用;
* 所謂的建構函式也可以當普通函式來用;
* 只是這種職能分配有悖常理。
* */
綜上所述,new操作符和建構函式的關係,好比廁所和上廁所的關係。
建構函式要用new呼叫,就好比上廁所就應該去廁所一樣。
但是,建構函式可以不用new呼叫嗎?
當然可以,這就好比隨地大小便,會汙染全域性環境。
new可以呼叫普通函式嗎?
當然可以,這就好比你不上廁所,卻可以留在廁所(傳說中的佔著茅坑不拉屎?)。
雖然有多種選擇,但是我們還是提倡用new呼叫建構函式這種組合,
就好像我們提倡不要隨地大小便一樣。
拷貝建構函式之我見
直接用乙個例子吧 定義乙個類test有乙個資料成員a。建構函式有兩個,乙個沒有引數,乙個傳入乙個test物件的位址。class test test test pt test 定義乙個test類物件aa,並修改其中資料成員a的值,然後用aa的位址作為引數來構造bb。void main 是可以的,bb的...
new建構函式和原型鏈
new建構函式functionpeople name,age 這個函式是不是建構函式?他沒有被呼叫,用new呼叫後就是建構函式,不被new呼叫就不是建構函式 functionpeople name,age varobj people 小明 12 alert obj null alert obj.ag...
new與建構函式
function cat name,age 機制1 每乙個函式物件都有乙個prototype物件 console.log cat.prototype node輸出 cat.prototype.get name function 機制2 new關鍵字 建構函式 step1 建立了乙個新的物件 該物件預...