日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

新手必看!JS 的 new 到底是干什么的?

 

大部分講 new 的文章會從面向對象的思路講起,但是我始終認為,在解釋一個事物的時候,不應該引入另一個更復雜的事物。

今天我從「代碼」的角度來講 new。

---------------------------

想象我們在制作一個策略類戰爭游戲,玩家可以操作一堆士兵攻擊敵方。

我們著重來研究一下這個游戲里面的「制造士兵」環節。

一個士兵的在計算機里就是一堆屬性,如下圖:

新手必看!JS 的 new 到底是干什么的?

 

我們只需要這樣就可以制造一個士兵:

var 士兵 = {
 ID: 1, // 用于區分每個士兵
 兵種:"美國大兵",
 攻擊力:5,
 生命值:42, 
 行走:function(){ /*走倆步的代碼*/},
 奔跑:function(){ /*狂奔的代碼*/ },
 死亡:function(){ /*Go die*/ },
 攻擊:function(){ /*糊他熊臉*/ },
 防御:function(){ /*護臉*/ }
}
兵營.制造(士兵)

制造一百個士兵

如果需要制造 100 個士兵怎么辦呢?

循環 100 次吧:

var 士兵們 = []
var 士兵
for(var i=0; i<100; i++){
 士兵 = {
 ID: i, // ID 不能重復
 兵種:"美國大兵",
 攻擊力:5,
 生命值:42, 
 行走:function(){ /*走倆步的代碼*/},
 奔跑:function(){ /*狂奔的代碼*/ },
 死亡:function(){ /*Go die*/ },
 攻擊:function(){ /*糊他熊臉*/ },
 防御:function(){ /*護臉*/ }
 }
 士兵們.push(士兵)
}
兵營.批量制造(士兵們)

哎呀好簡單。

質疑

上面的代碼存在一個問題:浪費了很多內存。

  1. 行走、奔跑、死亡、攻擊、防御這五個動作對于每個士兵其實是一樣的,只需要各自引用同一個函數就可以了,沒必要重復創建 100 個行走、100個奔跑……
  2. 這些士兵的兵種和攻擊力都是一樣的,沒必要創建 100 次。
  3. 只有 ID 和生命值需要創建 100 次,因為每個士兵有自己的 ID 和生命值。

改進

看過我們的專欄以前文章(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 之父的關懷

JS 之父創建了 new 關鍵字,可以讓我們少寫幾行代碼:

新手必看!JS 的 new 到底是干什么的?

 

只要你在士兵前面使用 new 關鍵字,那么可以少做四件事情:

  1. 不用創建臨時對象,因為 new 會幫你做(你使用「this」就可以訪問到臨時對象);
  2. 不用綁定原型,因為 new 會幫你做(new 為了知道原型在哪,所以指定原型的名字為 prototype);
  3. 不用 return 臨時對象,因為 new 會幫你做;
  4. 不要給原型想名字了,因為 new 指定名字為 prototype。

這一次我們用 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 的作用,就是省那么幾行代碼。(也就是所謂的語法糖)

注意 constructor 屬性

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(){ /*護臉*/ }
}

完。

分享到:
標簽:JS
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定