ES6函數的擴展
參數的默認值
在開發中,給函數的參數指定默認值,是很普遍很常見的一個需求,我們先來回顧一下傳統的實現方式,對比著看更好理解:
1 function person(n,a){ 2 var name = n || ‘Zhangsan‘; 3 var age = a || 25; 4 }
上面是傳統的實現方式,通過或運算實現,原理:如果運算符 || 左側為true,直接返回左側的值,否則返回右側的值; 在person函數內,如果參數n沒有傳參,那麽變量name得到的值就是“Zhangsan”,如果傳參了,變量name的值就為參數n的值。
但是,前提是參數對應的布爾值不能false(比如:數字0,空字符串等轉換成布爾值就是false),這就使得這種傳統的實現方式存在一定的不足和缺陷。
這個時候ES6說:“竟然這種寫法有缺陷,咱就不要用這種寫法了,我給你們帶來一種新的實現方式,比這種寫法好用多了,更簡捷”。
1 function person(name = ‘Zhangsan‘,age = 25){ 2 console.log(name,age); 3 } 4 5 person();//結果:Zhangsan 25 6 person(‘Lisi‘,18);//結果:Lisi 18
看,我們把默認值的設定放在了參數上:(name = ‘Zhangsan‘,age = 25),這樣就實現了參數name的默認值為‘Zhangsan’,age的默認值為25。而不需要在函數體內進行檢測,函數體內可以專註對參數的使用或者運算,再也不用擔心函數的實際傳參情況了。
上面的案例,我們對person( )函數進行兩次調用,區別是有傳參數和沒傳參數,運行的結果也符合我們的預期:沒傳參,得到的是默認值Zhangsan 25,傳參就會得到傳入的參數值:Lisi 18。
但是,多留個心眼,凡事總會有但是,如果函數有多個參數,但只有部分需要指定默認值,另一部分不需要的話,那麽,設定默認值的參數一定要放在最後。
1 //錯誤寫法 2 function person(age = 25,name){ 3 console.log(name,age); 4 } 5 6 //正確寫法 7 function person(name,age = 25){ 8 console.log(name,age); 9 }
上面的person函數,兩個參數name和age,其中只有age需要指定默認值,name不需要,那麽,age的排序就必須放在最後,name放在前面。也就是有默認值的參數後面不能再跟不需默認值的參數了。
另外,只有當傳入的參數為undefined,才會觸發默認值賦值。否則,哪怕你傳的參數值為0,false,null都不會觸發默認值賦值,這就完美的解決了傳統實現方式的弊端,試試看:
1 function person(age = 12){ 2 console.log(age); 3 } 4 5 person();//結果:12 6 person(undefined);//結果:12 7 8 person(0);//結果:0 9 person(null);//結果:null
看person( )函數的4次調用和結果,只有不傳或者傳入undefined的時候才會觸發默認值賦值,得到12,傳入數字0或者null都不會觸發默認值賦值。
還有一個要註意的地方,函數的參數是默認聲明的,聲明過的變量,就不能用let或者const關鍵字再次聲明,否則會報錯的,不信給你看一個案例:
1 function person(age = 12){ 2 let age = 25;//錯誤,再次聲明age 3 }
上面這種情況,函數被調用後,就會報錯,會提示你age已經被聲明過了,你別再聲明它了。
rest參數
rest參數,這是一個新的概念,rest的中文意思是:剩下的部分。
如果用在函數上,就代表是獲取函數剩下部分的參數。具體是什麽意思?我們還是得看案例才好理解,假設現在我們有這樣的一個需求:將一組數字進行求和,然後把求和的結果賦值到一個變量去,我們用rest參數實現:
1 //求和函數,得到的結果賦值到result 2 function sum(result,...values){ 3 //打印values看看是什麽 4 console.log(values); 5 //結果:[1,2,3,4] 6 7 //進行求和 8 values.forEach(function (v,i) { 9 //求和得到的結果存到result 10 result += v; 11 }); 12 //打印出求和的結果看看 13 console.log(result); 14 //結果:10 15 } 16 17 //存儲求和結果的變量res 18 var res = 0; 19 //調用sum函數 20 sum(res,1,2,3,4);
上面的代碼註釋把每一步都寫得很詳細,首先,我們會看到一個陌生的語法:...values;咦?這是什麽鬼?這是一種新的寫法,也就是我們要介紹的rest參數,它代表的意思是:在實參中,除了第一個參數以外,剩余的參數都會被...values獲取到。
在上面的案例中:sum(res,1,2,3,4),也就是除去實參 res 以外的參數,它們是1,2,3,4一共4個參數。它們全被...values收入囊中,接著,我們打印了values,看到的結果是一個數組:[1,2,3,4],也就是這4個參數被裝在了一個數組中,我們想要使用這4個參數的話,就可以用數組的方法來對他們進行處理,所以我們用了forEach方法對它們進行了循環,並求和,把求和結果存儲到了變量res中,最後我們打印出結果,得到了數字10,也就是數字1,2,3,4的求和結果。
(上面這段有點長,耐心讀完了嗎?讀不懂,可以拉上去再閱讀一遍上面的代碼案例)
上面的案例主要是介紹了rest參數的用法,首先是表示法:...values(三個點+變量名);其次,values是一個數組;我們要學會這兩點即可。
要註意的是,rest參數必須是函數的最後一個參數,後面不能再跟其他參數,什麽意思呢?看案例:
1 //錯誤寫法 2 function sum(result, ...values, mult){ 3 //rest參數...values後面還有一個參數mult 4 } 5 //正確的寫法 6 function sum(result, mult, ...values){ 7 //rest參數...values放在最後 8 }
上面有錯誤和正確的兩種表示,在註釋上有說明原因。總之rest參數後面不能再跟有其他參數。
rest參數並不是適合所有的函數使用,只在特定的情境下會比較適用,比方說剛剛案例中的求和函數,就十分適合要rest參數把實際的參數收集起來放在數組中進行求和,在適當的情況下使用它可以事半功倍,減少代碼量,提高開發效率。
擴展運算符
上面講到的rest參數,它的表示法使用...(三個點),它除了用在rest參數中,還有其他用途,我們稱這種表示法為擴展運算符,那麽,它還有什麽作用呢?
它一般結合數組使用,把數組的元素用逗號分隔開來,組成一個序列。我們看一下實際案例:
1 function sum(a,b) { 2 return a+b ; 3 } 4 5 let arr = [2,3]; 6 //用擴展運算法將數組[2,3]轉換成2,3 7 sum(...arr); 8 //結果:5
上面的sum( )函數是簡單的將兩個數字相加求和,參數是兩個普通的參數x,y,並不是什麽高逼格的rest參數,所以我們運用了擴展運算符...將數組[ 2,3 ] 轉成了 2,3 兩個普通的數列,再傳進sum( )方法,對應上x,y兩個參數。實際上,sum( ...arr ) 的效果相當於sum( 2,3 ) 。
從這個案例我們就可以理解擴展運算符...的作用了,它可以將一個數組轉成一個對應的參數數列。在實際開發中,你可以根據擴展運算符的作用,可以靈活運用,實現各種效果。
箭頭函數
箭頭函數,這又是一個新概念,ES6給我們介紹一種全新的定義函數的方式,就是用箭頭符號(=>),故得名為箭頭函數。具體怎麽用,我們來看案例:
1 //傳統寫法 2 var sum = function(a) { 3 return a ; 4 }; 5 6 //箭頭函數寫法 7 var sum = a => a;
上面演示了兩種寫法,函數的作用都是一樣的,傳入參數a,直接返回a;第一種傳統的寫法大家都熟悉,我們看看第二種寫法:a=>a; 這裏的第一個a代表是傳進去的參數,箭頭=>後面的a表示函數體;也許大家跟我一樣,很不習慣,但這種寫法確實簡潔了很多。
1 //箭頭函數寫法 2 var sum = (a,b) => {return a+b} 3 sum(1,2);//結果:3
註意上面的參數和函數體部分,如果參數超過1個的話,需要用小括號()括起來,函數體語句超過1條的時候,需要用大括號{ }括起來。
箭頭函數的最大作用就是簡化函數的實現,大大地減少代碼量。來舉個例子對比一下,假設我們現在要對一個數組 [ 1,2,3,4 ] 裏面的數求和,我們分別用傳統的方式和箭頭函數都實現一次,大家看看差別:
1 //傳統的寫法 2 var sum = 0; 3 [1,2,3,4].forEach(function(v){ 4 sum += v; 5 }); 6 7 //箭頭函數的寫法 8 var sum = 0; 9 [1,2,3,4].forEach(v => sum+=v);
大家對比一下,用箭頭函數代替了傳統的匿名函數,確實減少了代碼量。
今天講解的函數擴展都是一些新概念,新語法。也許你看懂了,但是過段時間會忘記,不用慌,這很正常,只有通過多練習、多使用才會記住。如果你現在的項目還未使用到這些知識的話,不妨先收藏起來,有空的時候翻看一下,也是很有幫助的,因為ES6是趨勢,總有一天會進入你的代碼中。
本節小結
總結:ES6為函數的擴展包括:參數的默認值、rest參數、擴展運算符(...)以及箭頭函數。它們有一個共同的有點就是:使得代碼更加簡潔,結合需求靈活使用,可以大大地提高開發效率。
ES6函數的擴展