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

results matching ""

    No results matching ""