學習記錄--《深入理解ES6》之函式(上)
帶引數預設值的函式
ES6中的引數預設值
ES6能更容易地為引數提供預設值,它使用了初始化形式,以便在引數未被正式傳遞進來時使用。
function makeRequest(url, timeout =2000, callback = funtcion(){}){
// 函式的剩餘部分
}
此函式只要求第一個引數始終要被傳遞。其餘兩個引數則都有預設值,這使得函式體更為小巧,因為不需要再新增更多程式碼來檢查缺失的引數值。
如果使用全部三個引數來呼叫makeRequest(), 那麼預設值將不會被使用
// 使用預設的timeout 與 callback
makeRequest("/foo");
//使用預設的callback
makeRequest("/foo",500);
//不使用預設值
makeRequest("/foo",500,function(body){
dosomething(body);
})
在函式宣告中能指定任意一個引數的預設值,即使該引數排在未指定預設值的引數之前也是可以的。
function makeRequest(url, timeout = 2000, callback){
//函式內容
}
// 使用預設的timeout
makeRequest("/foo",undefined, function(body){
doSomething(body);
});
// 使用預設的timeout
makeRequest("/foo");
//不使用預設值
makeRequest("/foo", null, function(body){
doSomething(body);
})
在關於引數預設值的這個例子中,null值被認為是有效的,意味著對於makeRequest()的第三次呼叫並不會使用timeout的預設值。
引數預設值如何影響arguments物件
需要記住的是,arguments 物件會在使用引數預設值時有不同的表現。在ES5的非嚴格模式下,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
在非嚴格模式下, arguments 物件總是會被更新以反映出具名引數的變化。因此當 first與 second 變數被賦予新值時, arguments[0] 與 arguments[1] 也就相應地更新了,使得這裡所有的 === 比較的結果都為 true 。
然而在使用ES6引數預設值的函式中,arguments物件的表現總是會與ES5的嚴格模式一致,無論此時函式是否明確執行在嚴格模式下。引數預設值的存在觸發了arguments物件與具名引數的分離。這是個細微但重要的細節,因為arguments物件的使用方式發生了變化。
// 非嚴格模式
function mixArgs(first, second = "b"){
console.log(arguments.length);
console.log(first === arguments[0]);
console.log(second === argument[1]);
first = "c";
second = "d";
console.log(first === arguments[0]);
console.log(second === arguments[1]);
}
mixArgs("a");
輸出
1
true
false
false
false
本例中arguments.length的值為1,因為只給 mixArgs() 傳遞了一個引數。這也意味著 arguments[1] 的值是undefined,符合將單個引數傳遞給函式時的預期;這同時意味著first與arguments[0]是相等的。改變first 和 second 的值不會對 arguments 物件造
成影響,無論是否在嚴格模式下,所以你可以始終依據 arguments 物件來反映初始呼叫狀態。
引數預設值的暫時性死區
前面介紹了let與const的暫時性死區,而引數預設值同樣有著無法訪問特定引數的暫時性死區。與let宣告相似,函式每個引數都會建立一個新的識別符號繫結,它在初始化之前不允許被訪問,否則會丟擲錯誤。引數初始化會在函式被呼叫時進行,無論是給引數傳遞一個值、還是使用了引數的預設值。
function ad(first = second, second){
return first + second;
}
console.log(add(1,1)); //2
console.log(add(undefined,1)); //丟擲錯誤
本例中呼叫add(1,1)與add(undefined,1)對應著以下的後臺程式碼:
//JS呼叫add(1,1) 可表示為
let first = 1;
let second = 1;
//JS呼叫add(1)可表示為
let first = second;
let second = 1;
本例中呼叫add(undefined,1)丟擲了錯誤,是因為在first被初始化時second尚未被初始化。此處的second 存在於暫時性死區內,對於second的引用就丟擲了錯誤。體現出let的繫結行為
函式引數擁有各自的作用域和暫時性死區,與函式體的作用域相分離,這意味著引數的預設值不允許訪問在函式體內部宣告的任意變數。
剩餘引數
剩餘引數(rest parameter)由三個點(…)與一個緊跟著的具名引數指定,它會是包含傳遞給函式的其餘引數的一個陣列,名稱中的“剩餘”也由此而來。
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;
}
剩餘引數的限制條件
剩餘引數受到兩點限制。
第一個限制是函式只能有一個剩餘引數,並且它必須被放在最後。例如,如下程式碼是無法工作的
// 語法錯誤:不能在剩餘引數後使用具名引數
function pick(object, ...keys, last){
let result = object.create(null);
for(let i = 0, len = keys.length; i < len; i++){
result[keys[i]] = object[keys[i]];
}
return result;
}
第二個限制 剩餘引數不能再物件字面量的setter屬性中使用,這意味著如下程式碼導致語法錯誤
let object = {
//語法錯誤:不能在setter中使用剩餘引數
set name(...value)
}
存在此限制的原因是:物件字面量的setter被限定只能使用單個引數;而剩餘引數按照定義是不限制引數數量的,因此它在此處不被許可。
剩餘引數如何影響arguments物件
設計剩餘引數是為了替代ES中的arguments。原先在ES4中就移除了arguments並新增了剩餘引數,以便允許向函式傳入不限數量的引數。儘管ES4從未被實施,但這個想法被保持下來並在ES6中重新引入,雖然arguments仍未在語言中被移除。
function checkArgs(...args){
console.log(args.length);
console.log(arguments.length);
console.log(args[0], arguments[0]);
console.log(args[1], arguments[1]);
}
checkArgs("a" , "b");
函式構造器的增強能力
Function 構造器允許你動態建立一個新函式,但在JS中並不常用。傳給該構造器的引數都是字串,它們就是目標函式的引數與函式體。
var add = new Function("first", "“second”, "return first + second" ;
console.log(add(1 , 1));
)
ES6增強了Function構造器的能力,允許使用預設引數以及剩餘引數。對於預設引數來說,你只需為引數名稱新增等於符號以及預設值。如下例:
var add = new Function("first" , "second = first", "return first + second");
console.log(add(1,1)); //2
console.log(add(1)); //2
//剩餘引數
var pickFirst = new Function("...args","return args[0]");
console.log(pickFirst(1,2));
擴充套件運算子
與剩餘引數關聯最密切的就是擴充套件運算子。
剩餘引數允許你把多個獨立的引數合併到一個陣列中
擴充套件運算子允許將一個陣列分割,並將各個項作為分離的引數傳給函式。
let values = [25, 50, 75, 100];
// 等價於 console.log(Math.max(25, 50, 75, 100));
console.log(Math.max(...values)); //100
//可以將擴充套件運算子與其他引數混用。
let values = [-25, -50, -75 ,-100];
console.log(Math.max(...values, 0)); //0
本例中傳給Math.max() 的最後一個引數是0,它跟在使用擴充套件運算子的其他引數之後傳入。
用擴充套件運算子傳遞引數,使得更容易將陣列作為函式引數來使用,你會發現在大部分場景中擴充套件運算子都是apply() 方法的合適替代品。
相關文章
- 深入理解ES6之函式函式
- 深入理解ES6 ---- 函式函式
- ES6深入學習(二)關於函式函式
- 函式 - Go 學習記錄函式Go
- 重讀《深入理解ES6》—— 函式函式
- ES6學習筆記(三)【函式,物件】筆記函式物件
- day10學習筆記之函式上筆記函式
- 深入理解ES6中的箭頭函式函式
- ES6語法學習筆記之函式預設引數筆記函式
- 【學習筆記】CSS深入理解之margin筆記CSS
- 【學習筆記】CSS深入理解之overflow筆記CSS
- 【學習筆記】CSS深入理解之relative筆記CSS
- PHP 第二週函式學習記錄PHP函式
- PHP 第五週函式學習記錄PHP函式
- PHP 第十週函式學習記錄PHP函式
- PHP 第七週函式學習記錄PHP函式
- PHP 第九周函式學習記錄PHP函式
- PHP 第三週函式學習記錄PHP函式
- PHP 第六週函式學習記錄PHP函式
- PHP 第一週函式學習記錄PHP函式
- ES6語法學習筆記之箭頭函式、剩餘引數筆記函式
- JS的學習理解--->函式JS函式
- PHP 第四周函式學習記錄PHP函式
- PHP 第十一週函式學習記錄PHP函式
- PHP 第十四周函式學習記錄PHP函式
- PHP 第十三週函式學習記錄PHP函式
- PHP 第十二週函式學習記錄PHP函式
- 【深入淺出ES6】函式函式
- iOS學習之深入理解RunLoopiOSOOP
- 檔案和目錄之stat族函式——APUE學習筆記(2)函式筆記
- JS學習理解之閉包和高階函式JS函式
- pandas之常用基本函式學習筆記函式筆記
- 閱讀《深入理解ES6》書籍,筆記整理(上)筆記
- 【學習筆記】CSS深入理解之vertical-align筆記CSS
- JS學習筆記之再理解一等公民--函式(基礎篇)JS筆記函式
- 深入理解 Generator 函式函式
- 深入理解ES6之《解構》
- 《深入理解 ES6》筆記 — 模組筆記