1. 程式人生 > >函式形參的預設值

函式形參的預設值

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;  

函式引數有自己的作用域和臨時死區,和函式體的作用域是獨立的,就是說函式引數預設值不能訪問函式體內宣告的變數