ES6函式新特性及箭頭函式與普通函式的區別
前言:專案中也經常用到es6的箭頭函式,但是也沒怎麼去細看es6更新了哪些函式特性,畢竟es7, es8都出來了。今天細看了《深入瞭解ES6》這本書的第三章,函式這一節,特此記錄一下es6更新了哪些函式的新特性。
1.函式形參的預設值。
e5及之前,設定預設引數值均在函式內部去判斷是否傳了該引數,未傳值便賦予預設值,說實話我現在還在用這種思維寫函式,看來要改一改了,不然真的沒點進步了。
舉例:
function makeRequest(url,timeout,callback){ timeout=timeout||2000; //未傳值是undefined,這種寫法不安全,傳入0也是false 設為預設值 callback=callback||function(){}; //doSomething } //安全寫法, function makeRequest(url,timeout,callback){ timeout=(typeof timeout!=="undefined")?timeout:2000; //雖安全但仍需額外程式碼來執行 callback=(typeof callback!=="undefined")?callback:function(){}; //doSomething }
而ES6中的預設引數值:若未為引數傳值或傳入undefined,則為其提供預設值
舉例:
function makeReques(url,timeout=2000,callback=function(){}){
//doSomething
}
預設引數的特點:
(1)預設引數對arguments物件的影響
es5非嚴格模式下,命名引數的變化會同步更新到arguments物件中。嚴格模式下將不會導致arguments改變
function mixArgs(first,second){//非嚴格模式 console.log(first===arguments[0]); console.log(second===arguments[1]); first="c",second="d"; console.log(first===arguments[0]); console.log(second===arguments[1]); } mixArgs("a","b"); true true true true //嚴格模式下 function mixArgs(first,second){ "use strict" console.log(first===arguments[0]); console.log(second===arguments[1]); first="c",second="d"; console.log(first===arguments[0]); console.log(second===arguments[1]); } mixArgs("a","b") true true false false
在es6中:無論是否顯示定義了嚴格模式,arguments物件都將與es5嚴格模式下保持一致,預設引數值的存在將使arguments物件與命名引數分離。
(2)預設引數表示式
//非原始值傳參: let value=5; function getValue(){ return value++; } function add(fiirst,second=getValue()){ return first+second; } console.log(add(1,1));//2 console.log(add(1));//6 console.log(add(7));//6 每呼叫一次 未傳第二各引數的add將改變value的值。
正因預設引數是在函式呼叫時求值,可使用先定義的引數作為預設值,反之不可,預設引數的臨時死區。
(3)預設引數的臨時死區
函式引數有自己的作用域和臨時死區,其與函式體的作用域是各自獨立的,就是說引數的預設值不可訪問函式體內宣告的變數。
2.不定引數
在命名引數前加三個點(...)就表明這是一個引數,該參是一個數組,包含著自他之後的所有引數,通過陣列名即可逐一訪問各個引數;
function pick(object,...keys){
let result=Object.create(null);
for(let i=0,len=keys.length;i<len;i++){
result[keys[i]]=object[keys[i]];
}
return result;
}
let as={title:"es6",name:'Nicks',years:2012};
pick(as,...["name","years"]);//{name: "Nicks", years: 2012}
ES5中無命名引數
javascripts提供arguments物件來檢查函式的所有引數,因此不必定義每個要用的引數。實際使用有些笨重,不如es6不定引數
舉例:
function pick(object){
let result=Object.create(null);
//從第二個引數開始
for(let i=1,len=arguments.length;i<len;i++){
result[arguments[i]]=object[arguments[i]];
}
return results;
}
let as={title:"es6",name:'Nicks',years:2012};
pick(as,"name","years");//{name: "Nicks", years: 2012}
不定引數的使用限制:
① 每個函式最多隻能宣告一個不定參,必須在所有引數的末尾
②不定參不能用於物件字面量setter之中
③無論是否是用不定引數arguments物件總是包含所有傳入函式的引數。
注:另外還有其他特性:增強Function建構函式、展開運算子、name屬性,明確多重用途,(this),元屬性new.target、塊級函式,在此不細細說明
3、箭頭函式
(1)與傳統函式不同之處:
①沒有this,super,arguments和new.target繫結,箭頭函式中的這些值由外圍最近一層非箭頭函式決定。
②不能通過new關鍵字呼叫。它沒有[[Construct]],所以不能用作建構函式。如用會報錯
③沒有原型(prototype)
④不可以改變this的繫結,函式內部的this值不可被改變,在函式的生命週期內始終保持一致。
⑤不支援arguments物件。所以只能通過命名引數和不定引數兩種形式訪問函式引數。
⑥不支援重複的命名函式。
(2)箭頭函式語法:
let 函式名=(引數1,引數2,...)=>{ };
當只有一個引數時,可直接寫引數名。箭頭後也可不跟{},直接跟表示式或要返回的值,物件字面量要用()括住。
辨識方法:typeof instanceof
(3)建立立即執行函式表示式:
是javasscript函式比較流行的使用方式,可定義一個匿名函式並立即呼叫,自始至終不儲存對該函式的引用。(想建立一個與其他程式隔離的作用域時,該模式比較方便)。
//es5
let person =function(name){
return {
getName:function(){
return name;
}
};
}("Nicholas");
console.log(person.getName());//"Nicholas"
//es6:
let person =((name)=>{
return {
getName:function(){
return name;
}
};
})("Nicholas");
consol.log(person.getName());//"Nicholas"
(3)ES6尾呼叫優化(尾呼叫系統的引擎優化)。
尾呼叫指的是函式作為另個函式的最後一句被呼叫:
function doSomething(){
return doSomethingElse();//尾呼叫
}
暫時也不太明白 ,書上是這麼說:尾呼叫優化可幫函式保持一個更小的呼叫棧,從而減少記憶體的使用,避免棧溢位錯誤,當程式滿足優化條件時,引擎會自動對其進行優化。
//遞迴:
function factorial(n){
if(n<=1){
return 1;
}else{
//無法優化,必在返回後執行乘法操作。
return n*factorial(n-1);
}
}
//ES6引擎優化:
function factorial(n,p=1){
if(n<=1){
return 1*p;
}else{
let result=n*p;
//優化後
return factorial(n-1,result);
}
}
暫時就瞭解這麼多,後續有新見解再多補充。