函式形參的預設值
ES6之前函式形參的預設值設定
當前一個運算元值為false時,總會返回後一個值。對於函式的命名引數,前一個運算元的值為false時,
總會返回後一個值,對於函式的命名引數,如果不顯示傳值,則其值預設為undefined,但是這個方法有缺陷
當我們為timeout傳入0時,即使這個值為合法的,boolean判斷仍為false
在這種情況下,更安全的是使用typeof
ES6 函式引數預設值
在這個函式中,只有第一個引數被認為是總要為其傳入值的,其他兩個引數都有預設值,而且不需要新增任何校驗值是否缺失的程式碼
makeRequest("/foo") // 使用引數timeout和callback的預設值
makeRequest("/foo", 500); // 使用引數callback的預設值
makeRequest("/foo", 500, function(body){doSomething(body)}); // 不使用預設值
按照ES6寫法,url是必需引數,宣告函式時,可以為任意引數指定預設值,在已指定預設值的引數後可以繼續宣告無預設值引數,例如:
在這種情況下,只有當不為第二個引數傳入值或主動為第二個引數傳入undefined時才會使用timeout的預設值,
makeRequest("/foo", undefined, function(body){doSomething(body);}); // 使用timeout預設值
makeRequest("/foo"); // 使用timeout預設值
makeRequest("/foo", null, function(body){doSomething(body);}); // 不使用timeout預設值
對於預設引數值,null也是一個合法值
預設引數值對arguments物件的影響
(1)ES5 非嚴格模式下
在非嚴格模式下,命名引數的變化會同步更新到arguments物件中
(2)ES5 嚴格模式下
無論命名引數如何變化,arguments物件將不再隨之改變,始終等於呼叫函式時傳入的引數值(即["a", "b"])
(3)ES6 中
ES6 中,如果一個函式使用了預設引數值,則無論是否顯示定義了嚴格模式,arguments物件的行為都將和ES5 嚴格模式下一致。
預設引數值的存在使得arguments物件保持與命名引數分離
只給函式傳遞一個引數在,則arguments[0] 值為 "a",arguments[1] 值為undefined,arguments.length為1;改變first 和second 不會影響arguments。
所以總是可以通過arguments物件將引數恢復為初始值
預設引數表示式
在上述程式碼中,如果不傳入最後一個引數,就會呼叫getValue()函式來得到正確的預設值
注意:初次解析函式不會呼叫getValue()方法,當呼叫add()方法且不傳入第二個引數時才會呼叫
當使用函式呼叫結果作為預設值時,如果忘記寫小括號,傳入的將是對函式的引用,而不是函式呼叫結果
因為預設引數是在函式呼叫時求值,所以可以使用先定義的引數作為後定義引數的預設值
還可以將first的值傳入一個函式來獲得second的值
在引用引數預設值的時候,只允許引用前面引數的值,即先定義的引數不能訪問後定義的引數。
預設引數的臨時死區
回顧上述例子,當呼叫add(1,1)時,相當於執行以下程式碼:
let first = 1;
let second = 1;
呼叫add(1)時,
let first = 1;
let second = getValue(first); // first 已經從臨時死區中解放出來了
上述程式碼:
呼叫add(1,1)時,
let first = 1;
let second = 1;
呼叫add(1)時,
let first = second; // 出錯,因為此時second還處於臨時死區中
let second = 1;
函式引數有自己的作用域和臨時死區,和函式體的作用域是獨立的,就是說函式引數預設值不能訪問函式體內宣告的變數