參數預設值
基本用法
ES6允許為函數參數設定預設值,即直接寫在參數定義後面。
function log(x, y = 'world') {
console.log(x, y);
}
log('Hello'); // Hello world
log('Hello', 'China'); // Hello China
log('Hello', ''); // Hello
ES6的寫法非常簡潔自然,如下例子:
function Point(x = 0, y = 0) {
this.x = x;
this.y = y;
}
var p = new Point();
p // {x:0, y:0}
除了簡潔,ES6的寫法還有兩個好處:
- 閱讀代碼的人,可以立刻意識到哪些參數是可以省略的,不用檢視函數體或文檔;
- 有利于将來代碼的優化,即使未來的版本在對外接口中,徹底去掉這個參數,也不會導緻以前的代碼無法運作。
參數變量是預設聲明的,是以不能用
let
或
const
再次聲明。
function foo(x = 0) {
let x = ; // error
const x = ; // error
}
上面代碼中,參數變量
x
是預設聲明的,在函數體中,不能用
let
或
const
再次聲明,否則會報錯。
與解構指派預設值結合使用
函數參數預設值是可以與解構指派(destructuring)的預設值,結合起來使用。
function foo({x, y = }) {
console.log(x, y);
}
foo({}); // undefined 1
foo({x: }); // 1 1
foo({x:, y: }); // 1 2
foo(); // TypeError: Cannot match against 'undefined' or 'null'.
上面代碼使用了對象的解構指派預設值,隻有當函數
foo
的參數是一個對象時,變量
x
和
y
才會通過解構指派生成,如果函數
foo
調用時參數不是對象,就無法進行解構指派,進而報錯。
參數預設值的位置
通常情況下,定義了預設值的參數,應該是函數的尾參數。因為這樣比較容易看出來,到底省略了哪些參數。如果非尾參數設定預設值,其實這個參數是沒法省略的。
function f(x = , y) {
return [x, y];
}
f(); // [1, undefined]
f(); // [1, undefined]
f(,); // [1, 1]
f(undefined, ); // [1, 1]
function func(x, y = , z) {
return [x, y, z];
}
func(); // [undefined, 1, undefined]
func(); // [1, 1, undefined]
func(, ,); // 報錯
func(, undefined, ); // [1, 1, 2]
上面例子中,有預設值的參數都不是尾參數,此時,無法隻省略該參數,而不省略它後面的參數,除非顯示傳入
undefined
。
函數的 length
屬性
length
函數指定了預設值後,函數的
length
屬性傳回的就不再是函數參數個數,而是第一個指定預設值的前面參數個數。也就是說指定了預設值後,函數的
length
屬性将失真。
(function(a) {}).length // 1
(function(a = 1) {}).length // 0
(function(a, b, c = 1, d) {}).length // 2
(function(...args) {}).length // 0
這是因為
length
屬性的含義是,該函數預期傳入的參數個數,某個參數指定預設值後,預期傳入的參數個數就不包括這個參數及其後面的參數。同時,Rest參數也不會計入
length
屬性。
作用域
一個需要注意的地方,如果參數預設值是一個變量,則該變量所處的作用域與其它變量的作用域一樣,即先是目前函數的作用域,然後才是全局作用域。
應用
利用參數預設值,可以指定某個參數不得省略,如果省略則抛出一個錯誤。
function throwIfMissing() {
throw new Error("Missing parameter");
}
function foo(mustBeGiven = throwIfMissing()) {
return mustBeGiven;
}
foo(); // Error: Missing parameter
上面代碼中
foo
函數,如果調用的時候沒有給出參數,則會調用預設值
throwIfMissing
函數,進而抛出一個錯誤。
此外,還可以将參數預設值設為
undefined
,表明這個參數是可以省略的。
function foo(optional = undefined) { ... }