參考書《ECMAScript 6入門》http://es6.ruanyifeng.com/函數的擴展函數的預設值 : ES6可以為函數指定預設值(1)指定預設值的兩種方式 a.函數參數的預設值 function test(a = 0,b = 5){ return a+b; } test();//5 ...
參考書《ECMAScript 6入門》
http://es6.ruanyifeng.com/
函數的擴展
函數的預設值 : ES6可以為函數指定預設值
(1)指定預設值的兩種方式
a.函數參數的預設值
function test(a = 0,b = 5){
return a+b;
}
test();//5 調用方法時,參數a,b都是undefined,可以使用預設值,因此返回5
test(7);//7+5 = 12
test(,10);//報錯 非尾參數設置了預設值,則調用函數時此參數無法忽略,忽略報錯;顯示傳入undefined,則觸發預設值
在參數中定義了預設值的變數,代碼塊中不能再用let或const重新定義變數(let與const不允許在同一個作用域內重覆聲明同一個變數)
function test3(a = 1){
let a = 7;
return a;
}
test3()//執行此方法時報錯(定義此方法test3時不報錯)Uncaught SyntaxError: Identifier 'a' has already been declared
function test4(b = 'sdf'){
const b = 'test4';
return b;
}
test4()//執行此方法時報錯(定義此方法test4時不報錯)Uncaught SyntaxError: Identifier 'b' has already been declared
function test5(c = 8){
var c = 1;
return c;
}
test5()//1 不報錯 let與const不允許在同一個作用域內重覆聲明同一個變數,而var可以,所以使用var重覆聲明c不報錯
使用參數的預設值時,不可以在聲明同名參數
function test6(a = 1, a, b){
return a+b;
}//函數定義時就報錯 Uncaught SyntaxError: Duplicate parameter name not allowed in this context
b.對象的解構賦值預設值
function test2({a = 1,b = 8}){
return a+b;
}
test2({});//9此時參數是一個空對象,空對象里的屬性全是undefined, 所以函數可以使用參數的預設值
test2({a:12,b:13});//25
test2({a:15});//23
test2();//此處使用的是對象的解構賦值預設值,如果傳入的參數不是對象,就無法讓對象的解構賦值預設值生效,報錯 Cannot destructure property `a` of 'undefined' or 'null'.
//要解決此問題,可以將其轉化為進一步的參數預設值
function test2({a = 2,b = 3} = {}){ //此處表示函數test2的預設參數是一個空對象,此空對象的屬性a的預設值是2,屬性b的預設值是3
return a+b;
}
test2({});//5
test2();//5
(2)指定預設值後length屬性將失真,已經制定預設值的參數以及位置在其後的參數都不參與length計數
function test7(a,b,c,d){
return a+b+c+d;
}
test7.length //4
function test8(a,b = 0,c,d){
return a+b+c+d;
}
test8.length //1 只計算了一個參數a,定義了預設值的參數b以及其後的c,d均不參與length計數
(3)參數預設值是不傳值的,如果參數預設值是一個表達式賦值,那每次都需要重新計算
(4)一旦設置了參數的預設值,函數進行聲明初始化時,參數會形成一個單獨的作用域(context)。等到初始化結束,這個作用域就會消失。這種語法行為,在不設置參數預設值時,是不會出現的。
(5)參數預設值用途:可用於提示某參數可省略(預設值設置成undefined)或者必須(預設值設置成可以返回異常提示語句的函數)
2.rest參數:rest參數是一個數組,length屬性不記錄rest參數。
function test11(...restParams){
return restParams;
}
test11(1,3,4,5,'qwe'); // [1,3,4,5,'qwe']
test11.length; //0
3.函數的name屬性返回實際的函數名
let f = function test12(){};
f.name; // 'test12'
Array.bind({}).name; // "bound Array"
4.箭頭函數
(1)箭頭函數的this始終是函數定義時的this,不是使用時的this
function Timer(){
this.s1 = 0;
this.s2 = 0;
setInterval(()=>this.s1++,1000);//箭頭函數中的this,指向Timer定義時的this,即this.s1 = 0;
setInterval(function(){
this.s2++;//常規寫法函數中的this,通常指向使用時的window/document全局變數,因此this.s2是NaN,而timer.s2始終是定義時的值。
},1000);
}
var timer = new Timer();
setTimeout(()=>console.log(timer.s1),3100);//3
setTimeout(()=>console.log(timer.s2),3100);//0
(2)箭頭函數可以簡化函數寫法
function insert(value){
return {into : function(arr){
return {afterValue : function(val){
arr.splice(arr.index(val)+1,0,value);
return arr;}
}}}
}
let insert = (value) => {into : (arr) => ({afterValue : (val) => {arr.splice(arr.indexOf(val)+1,0,value);return arr;}})}
(3)如果箭頭函數右邊返回的是代碼塊,用{}括起來;如果箭頭函數右邊的是對象,則必須使用({})括起來。
(a,b) => {return a+b}
let test13 = (a,b) => ({name : a,value : b})
test13("test",8); //{name : "test",value : 8}
(4)箭頭函數不能做構造函數,即不能使用new命令
let test15 = (a,b) => a*b;
new test15(); //報錯 Uncaught TypeError: test15 is not a constructor
5.雙冒號運算符:左邊是一個對象,右邊是一個函數
object1 :: f1 //等同於f1.bind(object1)
object2 :: f2(...restArr) //等同於 f2.apply(object2,restArr);
::f3 //等同於f3.bind(f3)
::f3(...restArr1) //等同於f3.apply(f3,restArr1);
如果雙冒號運算符的結果是一個對象,則可以鏈式使用
6.尾調用和尾調用優化
尾調用:函數的最後一步調用了另外一個函數
function test17(){
return test18();//必須是最後一步調用此函數,而且是作為返回值返回
}
尾調用優化:函數A最後一步調用了另外一個函數B,且函數B執行過程中不需要使用到任何有關函數A里變數的操作,那麼在尾調用執行後,有關函數A的調用幀都可以刪除,只保留函數B的調用幀,這即是尾調用優化
function A(a){
a = a + 1;
function B(b){
console.log(b);
}
return B('this is a test')
}
7.遞歸和尾遞歸
遞歸:函數調用自身
尾遞歸:函數尾調用自身
常見遞歸:遍歷dom樹
function traversal(node){
//對node的處理
if(node && node.nodeType === 1){
console.log(node.tagName);
}
var i = 0, childNodes = node.childNodes,item;
for(; i < childNodes.length ; i++){
item = childNodes[i];
if(item.nodeType === 1){
//遞歸先序遍歷子節點
traversal(item);//屬於尾遞歸
}
}
}
尾遞歸優化
普通尾遞歸
function sum(x){
if(x === 1) {return 1};
return x+sum(x - 1);//返回當前層次計算的x的值與下一子自身調用返回的值,因此當前的調用幀不能刪除
}
優化後的尾遞歸
function sum(x,y){
if(x === 1) {return y};
return sum(x - 1,x+y);//執行後當前調用幀可以刪除,進入下一次自調用的新參數的調用幀
}
5,1-->4,5+1
4,6-->3,5+1+4
3,11-->2,5+1+4+3
2,14-->1,5+1+4+3+2
1,15--->15
8.尾逗號規則:ES6允許函數定義時尾參數帶逗號
function test16(p1,p2,p3,){}