自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

反思JavaScript:論for循環(huán)的死亡

開(kāi)發(fā) 前端
你會(huì)如何進(jìn)一步分解這些函數(shù)?仔細(xì)想想“小于”或者name屬性、map或filter,說(shuō)不定能有額外的收獲。你還可以研究下函數(shù)的復(fù)合,收益更大。

我們一直在使用JavaScript的for循環(huán)。但現(xiàn)在,在最新的函數(shù)式編程技巧的支持下,過(guò)時(shí)的它應(yīng)該退休了。幸運(yùn)的是,你不必是一個(gè)函數(shù)式編程大師,也可以做出這個(gè)改變。更幸運(yùn)的是,這就是你在眼前項(xiàng)目中可以立馬做的事情!

[[183082]]

我們一直在使用JavaScript的for循環(huán)。但現(xiàn)在,在最新的函數(shù)式編程技巧的支持下,過(guò)時(shí)的它應(yīng)該退休了。

幸運(yùn)的是,你不必是一個(gè)函數(shù)式編程大師,也可以做出這個(gè)改變。更幸運(yùn)的是,這就是你在眼前項(xiàng)目中可以立馬做的事情!

那到底JavaScript的for循環(huán)有什么問(wèn)題?

for循環(huán)設(shè)計(jì)本身鼓勵(lì)改變狀態(tài)以及產(chǎn)生副作用,這兩者都是導(dǎo)致錯(cuò)誤和不可預(yù)知代碼的隱患。

我們都知道全局狀態(tài)是糟糕的,應(yīng)該避免。可是,局部狀態(tài)和全局狀態(tài)一樣糟糕,只是因?yàn)榫植繝顟B(tài)處于一個(gè)較小的尺度中,沒(méi)有引起注意。因此,我們從來(lái)沒(méi)有真正解決問(wèn)題,而是盡量把問(wèn)題最小化。

對(duì)于可變的狀態(tài),在一些未知的時(shí)間點(diǎn),變量會(huì)因?yàn)槟承┪粗脑蚨淖?。這時(shí),你要花上數(shù)小時(shí)進(jìn)行調(diào)試,尋找這個(gè)值改變的原因。光為這,我都不知道自己掉了多少把頭發(fā)了。

下面,我想簡(jiǎn)單談?wù)劯弊饔?。這個(gè)詞聽(tīng)起來(lái)就煩人,副作用……媽蛋!難道你會(huì)希望自己的程序有什么副作用?當(dāng)然不!

但什么是副作用?

當(dāng)一個(gè)函數(shù)修改了其作用域以外的某些東西時(shí),它就被視為有副作用??梢允歉淖円粋€(gè)變量的值、讀取鍵盤(pán)輸入、調(diào)用某個(gè)API、寫(xiě)入磁盤(pán)數(shù)據(jù)、打印日志,等等。

副作用很強(qiáng)大,但同時(shí)也被承擔(dān)著重大的責(zé)任。

副作用應(yīng)該盡可能被消除,或者封裝在內(nèi)部,或可控。有副作用的函數(shù)難以測(cè)試,也難以推斷,所以要盡你所能甩掉它。幸好這里可以不用擔(dān)心副作用。

好了,閑話少說(shuō),上代碼。我們看一下這段或許你已經(jīng)看過(guò)上千次典型的for循環(huán):

  1. const cats = [ 
  2.   { name: 'Mojo',    months: 84 }, 
  3.   { name: 'Mao-Mao', months: 34 }, 
  4.   { name: 'Waffles', months: 4 }, 
  5.   { name: 'Pickles', months: 6 } 
  6.  
  7. var kittens = [] 
  8.  
  9. // 典型的拙劣寫(xiě)法:for循環(huán) 
  10. for (var i = 0; i < cats.length; i++) { 
  11.   if (cats[i].months < 7) { 
  12.     kittens.push(cats[i].name) 
  13.   } 
  14.  
  15. console.log(kittens) 

我計(jì)劃將這些代碼一步一步重構(gòu),讓你清楚地看到將這些代碼轉(zhuǎn)換成更漂亮的寫(xiě)法是多么容易。

第一個(gè)改變就是把if里的聲明抽象為一個(gè)函數(shù):

  1. const isKitten = cat => cat.months < 7 
  2.  
  3. var kittens = [] 
  4.  
  5. for (var i = 0; i < cats.length; i++) { 
  6.   if (isKitten(cats[i])) { 
  7.     kittens.push(cats[i].name) 
  8.   } 

通常,抽出if語(yǔ)句是個(gè)不錯(cuò)的做法。過(guò)濾的著眼點(diǎn)從“小于7個(gè)月”轉(zhuǎn)變?yōu)?ldquo;是一只小貓”非常非常重要?,F(xiàn)在,當(dāng)你再看這段代碼,意圖就變得清晰了。為什么要取得小于7個(gè)月的貓?一點(diǎn)都不明確。我們的意圖是找到小貓,所以讓代碼表示出來(lái)!

另一個(gè)好處是iskitten現(xiàn)在可復(fù)用了,而且我們都明白:

讓代碼可復(fù)用應(yīng)該始終是我們的目標(biāo)之一。

下一個(gè)改變就是提取出從對(duì)象貓到貓名字的轉(zhuǎn)換(或者映射)。這個(gè)變化對(duì)以后更有意義,現(xiàn)在只要相信我就好了:

  1. const isKitten = cat => cat.months < 7 
  2. const getName = cat => cat.name 
  3.  
  4. var kittens = [] 
  5.  
  6. for (var i = 0; i < cats.length; i++) { 
  7.   if (isKitten(cats[i])) { 
  8.     kittens.push(getName(cats[i])) 
  9.   } 

我本打算先介紹一下filter和map的,但轉(zhuǎn)念一想,還是直接展示引入它們之后的代碼多好理解,更能讓你體會(huì)到代碼可讀性的巨大變化:

  1. const isKitten = cat => cat.months < 7 
  2. const getName = cat => cat.name 
  3.  
  4. const kittens = 
  5.   cats.filter(isKitten) 
  6.       .map(getName) 

還要注意,我們已經(jīng)消除了 kittens.push(...)。不再有可變的狀態(tài),也不再有var!

使用const的代碼有如魔鬼般性感(超過(guò)了var和let)。

這里說(shuō)明下,我們自始至終都可以使用const,因?yàn)閏onst并不會(huì)使對(duì)象本身不可變(這個(gè)咱們下次再說(shuō))。別急,這里只是在講一個(gè)范例,所以先放我一馬!

重構(gòu)的最后一步就是把過(guò)濾和映射方法也提取到一個(gè)函數(shù)里(為了復(fù)用嘛,你懂的):

整合一起就是這樣:

  1. const isKitten = cat => cat.months < 7 
  2. const getName = cat => cat.name 
  3. const getKittenNames = cats => 
  4.   cats.filter(isKitten) 
  5.       .map(getName) 
  6.  
  7. const cats = [ 
  8.   { name: 'Mojo',    months: 84 }, 
  9.   { name: 'Mao-Mao', months: 34 }, 
  10.   { name: 'Waffles', months: 4 }, 
  11.   { name: 'Pickles', months: 6 } 
  12.  
  13. const kittens = getKittenNames(cats) 
  14.  
  15. console.log(kittens) 

你會(huì)如何進(jìn)一步分解這些函數(shù)?仔細(xì)想想“小于”或者name屬性、map或filter,說(shuō)不定能有額外的收獲。你還可以研究下函數(shù)的復(fù)合,收益更大。

原    文:Rethinking JavaScript: Death of the For Loop
譯    文:眾成翻譯
作    者:camiler
責(zé)任編輯:張燕妮 來(lái)源: 眾成翻譯
相關(guān)推薦

2012-01-18 09:26:05

SaaS云計(jì)算

2012-07-06 13:54:59

JavaScript

2011-05-25 16:23:35

Javascript類繼承

2014-03-14 10:07:09

極限編程敏捷開(kāi)發(fā)

2017-03-28 21:25:19

無(wú)循環(huán)代碼JavaScript

2022-03-11 14:59:21

JavaScript數(shù)組字符串

2016-09-06 21:23:25

JavaScriptnode異步

2013-05-28 00:35:48

JavaScriptfor循環(huán)

2022-01-12 15:50:24

JavaScript開(kāi)發(fā)循環(huán)

2017-01-20 08:30:19

JavaScriptfor循環(huán)

2020-03-02 19:28:03

人工智能AI

2011-09-16 15:10:46

Android應(yīng)用IOS應(yīng)用Death App

2015-08-11 08:51:40

游戲死亡

2012-07-16 09:45:44

降級(jí)論傻蛋

2023-09-13 08:00:00

JavaScript循環(huán)語(yǔ)句

2015-11-02 19:11:27

阮一峰javascript循環(huán)加載

2024-08-30 08:43:24

JavaScriptforEachfor循環(huán)

2021-01-18 08:24:51

JavaScriptMicrotask微任務(wù)

2014-02-13 17:21:23

技術(shù)創(chuàng)業(yè)

2011-10-17 08:29:33

Ubuntu 11.1思考
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)