做者:方應杭 連接:https://zhuanlan.zhihu.com/p/23987456 著做權歸做者全部。商業轉載請聯繫做者得到受權,非商業轉載請註明出處。前端
大部分講 new 的文章會從面向對象的思路講起,可是我始終認爲,在解釋一個事物的時候,不該該引入另外一個更復雜的事物。(對的,我在含蓄地「黑」面向對象)bash
今天我從「省代碼」的角度來說 new。函數
致說我囉嗦的人:學習
想象咱們在製做一個策略類戰爭遊戲,玩家能夠操做一堆士兵攻擊敵方。ui
咱們着重來研究一下這個遊戲裏面的「製造士兵」環節。this
一個士兵的在計算機裏就是一堆屬性,以下圖:spa
咱們只須要這樣就能夠製造一個士兵:prototype
var 士兵 = {
ID: 1, // 用於區分每一個士兵
兵種:"美國大兵",
攻擊力:5,
生命值:42,
行走:function(){ /*走倆步的代碼*/},
奔跑:function(){ /*狂奔的代碼*/ },
死亡:function(){ /*Go die*/ },
攻擊:function(){ /*糊他熊臉*/ },
防護:function(){ /*護臉*/ }
}
兵營.製造(士兵)
複製代碼
若是須要製造 100 個士兵怎麼辦呢?code
循環 100 次吧:cdn
var 士兵們 = []
var 士兵
for(var i=0; i<100; i++){
士兵 = {
ID: i, // ID 不能重複
兵種:"美國大兵",
攻擊力:5,
生命值:42,
行走:function(){ /*走倆步的代碼*/},
奔跑:function(){ /*狂奔的代碼*/ },
死亡:function(){ /*Go die*/ },
攻擊:function(){ /*糊他熊臉*/ },
防護:function(){ /*護臉*/ }
}
士兵們.push(士兵)
}
兵營.批量製造(士兵們)
複製代碼
哎呀好簡單。
上面的代碼存在一個問題:浪費了不少內存。
看過咱們的專欄之前文章(JS 原型鏈)的同窗確定知道,用原型鏈能夠解決重複建立的問題:咱們先建立一個「士兵原型」,而後讓「士兵」的 __proto__
指向「士兵原型」
var 士兵原型 = {
兵種:"美國大兵",
攻擊力:5,
行走:function(){ /*走倆步的代碼*/},
奔跑:function(){ /*狂奔的代碼*/ },
死亡:function(){ /*Go die*/ },
攻擊:function(){ /*糊他熊臉*/ },
防護:function(){ /*護臉*/ }
}
var 士兵們 = []
var 士兵
for(var i=0; i<100; i++){
士兵 = {
ID: i, // ID 不能重複
生命值:42
}
/*實際工做中不要這樣寫,由於 __proto__ 不是標準屬性*/
士兵.__proto__ = 士兵原型
士兵們.push(士兵)
}
兵營.批量製造(士兵們)
複製代碼
有人指出建立一個士兵的代碼分散在兩個地方很不優雅,因而咱們用一個函數把這兩部分聯繫起來:
function 士兵(ID){
var 臨時對象 = {}
臨時對象.__proto = 士兵.原型
臨時對象.ID = ID
臨時對象.生命值 = 42
return 臨時對象
}
士兵.原型 = {
兵種:"美國大兵",
攻擊力:5,
行走:function(){ /*走倆步的代碼*/},
奔跑:function(){ /*狂奔的代碼*/ },
死亡:function(){ /*Go die*/ },
攻擊:function(){ /*糊他熊臉*/ },
防護:function(){ /*護臉*/ }
}
// 保存爲文件:士兵.js
複製代碼
而後就能夠愉快地引用「士兵」來建立士兵了:
var 士兵們 = []
for(var i=0; i<100; i++){
士兵們.push(士兵(i))
}
兵營.批量製造(士兵們)
複製代碼
JS 之父建立了 new 關鍵字,可讓咱們少寫幾行代碼:
只要你在「士兵」前面使用 new 關鍵字,那麼能夠少作四件事情:
function 士兵(ID){
this.ID = ID
this.生命值 = 42
}
士兵.prototype = {
兵種:"美國大兵",
攻擊力:5,
行走:function(){ /*走倆步的代碼*/},
奔跑:function(){ /*狂奔的代碼*/ },
死亡:function(){ /*Go die*/ },
攻擊:function(){ /*糊他熊臉*/ },
防護:function(){ /*護臉*/ }
}
// 保存爲文件:士兵.js
複製代碼
而後是建立士兵(加了一個 new 關鍵字):
var 士兵們 = []
for(var i=0; i<100; i++){
士兵們.push(new 士兵(i))
}
兵營.批量製造(士兵們)
複製代碼
new 的做用,就是省那麼幾行代碼。
new 操做爲了記錄「臨時對象是由哪一個函數建立的」,因此預先給「士兵.prototype」加了一個 constructor 屬性:
士兵.prototype = {
constructor = 士兵
}
複製代碼
若是你從新對「士兵.prototype」賦值,那麼這個 constructor 屬性就沒了,因此你應該這麼寫:
士兵.prototype.兵種 = "美國大兵"
士兵.prototype.攻擊力 = 5
士兵.prototype.行走 = function(){ /*走倆步的代碼*/}
士兵.prototype.奔跑 = function(){ /*狂奔的代碼*/ }
士兵.prototype.死亡 = function(){ /*Go die*/ }
士兵.prototype.攻擊 = function(){ /*糊他熊臉*/ }
士兵.prototype.防護 = function(){ /*護臉*/ }
複製代碼
或者你也能夠本身給 constructor 從新賦值:
士兵.prototype = {
constructor: 士兵,
兵種:"美國大兵",
攻擊力:5,
行走:function(){ /*走倆步的代碼*/},
奔跑:function(){ /*狂奔的代碼*/ },
死亡:function(){ /*Go die*/ },
攻擊:function(){ /*糊他熊臉*/ },
防護:function(){ /*護臉*/ }
}
複製代碼
完。
喜歡本文的話,請關注知乎專欄《前端學習指南》
想學前端?到 Q 羣裏找我:566475505 ,加羣暗號:來自掘金