11.3 默认参数值
ECMAScript 6 允许给参数指定默认值:
function f(x, y=0) {
return [x, y];
}
省略第二个参数就会触发默认值:
> f(1)
[1, 0]
> f()
[undefined, 0]
当心 - undefined
也会触发默认值:
> f(undefined, undefined)
[undefined, 0]
默认值仅在需要的时候在后台计算:
> const log = console.log.bind(console);
> function g(x=log('x'), y=log('y')) {return 'DONE'}
> g()
x
y
'DONE'
> g(1)
y
'DONE'
> g(1, 2)
'DONE'
11.3.1 为什么 undefined
会触发默认值?
为什么 undefined
应该被当成一个缺失的参数,或者对象或数组的缺失部分?这个问题不是显而易见的。这么做的原理是它使你能够把默认值的定义转移到其它地方去。让我们看两个例子。
第一个例子(来源: Rick Waldron’s TC39 meeting notes from 2012-07-24 ),在 setOptions()
中不需要定义一个默认值,可以把这个任务转移到 setLevel()
。
function setLevel(newLevel = 0) {
light.intensity = newLevel;
}
function setOptions(options) {
// Missing prop returns undefined => use default
setLevel(options.dimmerLevel);
setMotorSpeed(options.speed);
···
}
setOptions({speed:5});
第二个例子, square()
不必为 x
定义一个默认值,可以将这个任务转移到 multiply()
:
function multiply(x=1, y=1) {
return x * y;
}
function square(x) {
return multiply(x, x);
}
默认值更进一步强调了 undefined
指代不存在的内容而 null
指代空( emptiness )的语意。
11.3.2 在默认值中使用其它变量
在参数的默认值中,可以使用任何变量,包括其它参数:
function foo(x=3, y=x) { ··· }
foo(); // x=3; y=3
foo(7); // x=7; y=7
foo(7, 2); // x=7; y=2
然后,顺序很重要:参数从左到右声明,因此在默认值中,如果去访问一个还没声明的参数,将会抛出 ReferenceError
异常。
默认值存在于它们自己的作用域中,该作用域介于包裹函数的“外部”作用域和函数体“内部”作用域之间。因此,在默认值中不能访问函数内部的变量:
let x = 'outer';
function foo(a = x) {
let x = 'inner';
console.log(a); // outer
}
在上面的例子中,如果没有外部的 x
,默认值 x
将会产生一个 ReferenceError
异常。
如果默认值是闭包,该限制可能让人非常吃惊:
function foo(callback = () => BAR) {
const BAR = 3; // can’t be accessed from default value
callback();
}
foo(); // ReferenceError