函数默认值
function hello(name = 'Mr Wang') {
console.log(`hello ${name}`)
}
hello(); // hello Mr Wang
参数变量默认声明,不能用let或const再次声明
function hello(name = 'Mr Wang') {
let name = 'Mr Li' //报错
console.log(`hello ${name}`)
}
参数默认值不是传值的,而是每次都重新计算表达式的值
let x = 100;
let add = (p = x + 1) => {
console.log(p)
}
add(); // 101
x = 200;
add(); // 201
上面代码中,参数p默认值是x+1。每次调用函数时,都会重新计算x+1,而不是默认等于100
与解构赋值默认值结合使用
function foo({ x, y = 0 }) {
console.log(x, y)
}
foo({}); // undefined 0
foo({ x: 0 }); // 0 0
foo({ x: 1, y: 1 }); // 1 1
foo(); //报错:TypeError: Cannot read property 'x' of undefined
上面代码只使用了对象的解构赋值默认值,没有使用函数参数的默认值。如果函数foo调用时没提供参数,变量x和y不会生成,从而报错。
解决办法:通过函数参数的默认值,避免报错
function foo({ x, y = 0 } = {}) {
console.log(x, y)
}
foo({}); // undefined 0
foo({ x: 0 }); // 0 0
foo({ x: 1, y: 1 }); // 1 1
foo(); // undefined 0
举个🌰
function fetch(url, { body = '', method = 'GET', headers = {} }) {
console.log(method)
}
fetch('htttp://test.com', {}); // GET
fetch('http://test.com');//报错
解决报错
function fetch(url, { body = '', methods = 'GET', headers = {} } = {}) {
console.log(methods);
}
fetch('http://test.com'); // GET
上面代码中,函数fetch没有第二个参数时,函数参数的默认值就回生效,然后才是解构赋值的默认值生效。method才能取到GET
参数默认值位置
通常情况下,定义了默认值的参数,应该是函数的尾参数。因为这样比较容易看出来,到底省略了哪些参数。如果非尾部的参数设置默认值,实际上这个参数是没法省略的。
函数的length属性
函数的length属性将返回没有指定默认值的参数个数。
console.log((function(a) {}).length) // 1
console.log((function(x, y = 1) {}.length)) // 1
console.log((function(x = 1, y = 1) {}.length)) // 0
console.log((function(x, y, z = 1) {}.length)) // 2
如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数
console.log((function(x, y = 1, z) {}.length)) // 1
console.log((function(x = 1, y, z) {}.length)) // 0
作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域。等到初始化结束,这个作用域消失,这种语法行为在不设置参数默认值时,是不会出现的。
var a = 1;
function foo(a, b = a) {
console.log(b)
}
foo(2); // 2
//参数y的默认值等于变量x,调用函数时,参数形成一个单独的作用域,在这个作用域里,默认值变量x指向的第一个参数x,而不是全局变量x,所以输出是2
另一个🌰
let a = 1;
function foo(b = a) {
let a = 2;
console.log(b);
}
foo(); // 1
上面代码中,函数foo调用时,参数b = a形成一个单独的作用域。这个作用域里面,变量a本身没有定义,所以指向外层的全局变量a。函数调用时,函数体内部的局部变量a影响不到默认值变量a
//如果此时没有全部变量的话,就回报错
function foo(b = a) {
let a = 2;
console.log(b);
}
foo(); // 报错
复杂的🌰
var x = 1;
function foo(x, y = function() { x = 2; }) {
//函数foo内部变量x就指向第一个参数x,与匿名函数的内部x一致
x = 3;
y();
console.log(x);
}
foo() // 2
应用
利用参数默认值,可以指定某一个参数不得省略,如果省略就抛出一个错误。
function throwIfMissing() {
throw new Error('Missing parameter');
}
function foo(mustBeProvided = throwIfMissing()) {
return mustBeProvided
}
foo(); // Error: Missing parameter
如果将参数的默认值设置为undefined,表明这个参数是可以省略的
function foo(optional = undefined){}