参数默认值
基本用法
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 = 1; // error
const x = 2; // error
}
上面代码中,参数变量x
是默认声明的,在函数体中,不能用let
或const
再次声明,否则会报错。
与解构赋值默认值结合使用
函数参数默认值是可以与解构赋值(destructuring)的默认值,结合起来使用。
function foo({x, y = 1}) {
console.log(x, y);
}
foo({}); // undefined 1
foo({x: 1}); // 1 1
foo({x:1, y: 2}); // 1 2
foo(); // TypeError: Cannot match against 'undefined' or 'null'.
上面代码使用了对象的解构赋值默认值,只有当函数foo
的参数是一个对象时,变量x
和y
才会通过解构赋值生成,如果函数foo
调用时参数不是对象,就无法进行解构赋值,从而报错。
参数默认值的位置
通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾参数设置默认值,其实这个参数是没法省略的。
function f(x = 1, y) {
return [x, y];
}
f(); // [1, undefined]
f(1); // [1, undefined]
f(,1); // [1, 1]
f(undefined, 1); // [1, 1]
function func(x, y = 1, z) {
return [x, y, z];
}
func(); // [undefined, 1, undefined]
func(1); // [1, 1, undefined]
func(1, ,2); // 报错
func(1, undefined, 2); // [1, 1, 2]
上面例子中,有默认值的参数都不是尾参数,此时,无法只省略该参数,而不省略它后面的参数,除非显示传入undefined
。
函数的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) { ... }