ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。
function log(x,y='World'){
console.log(x,y);
}
log('Hello');/*Hello World*/
log('Hello','China');/*Hello China*/
log('Hello','');/*Hello*/
function Point(x=0,y=0){
this.x = x;
this.y = y;
}
const p = new Point();
p/*{x:0,y:0}*/
参数变量是默认声明的,所以不能在函数体中再次声明;
参数默认值可以与解构赋值的默认值结合起来使用:
function fetch(url, { body = '', method = 'GET', headers = {} }){
console.log(method);
}
fetch('http://example.com',{});/*GET*/
fetch('http://example.com');/*报错*/
上述函数fetch的第二个参数是一个对象,可以为三个属性设置默认值;这种写法不能省略第二个参数,否则会报错;
但如果结合函数参数的默认值,就可以省略第二个参数(双重默认值)如下:
function fetch(url, { body = '', method = 'GET', headers = {} } = {}){
console.log(method);
}
fetch('http://example.com');/*GET*/
定义了默认值的参数,应该是函数的尾参数,如果非尾部的参数设置默认值,实际上这个参数无法省略(如下):
function f( x, y = 5, z ){
return [x, y, z];
}
f(); /*[undefined, 5, undefined]*/
f(1); /*[1, 5, undefined]*/
f(1, ,2); /*报错*/
f(1, undefined, 2); /*[1, 5, 2]*/
f(1, null, 2); /*[1, null, 2]*/
参数默认值位置
上述代码中,有默认值的参数都不是尾参数,
可全部省略(如上第一条);
可省略有默认值参数的参数以及后边的参数(如上第二条);
若只省略有默认值的参数,则会报错(如上第三条);
这时无法只省略该参数,而不省略他后边的参数,除非显示输入undefined;因为如果传入undefined,将触发该参数等于默认值(如上第四条);
null不可以(如上第五条)。
函数的length属性:
(function(...args) {}).length:将返回没有指定默认值的参数个数,但如果设置了默认值的参数不是尾参数,则length属性也不再计入后边的参数了。
函数的length属性,不包括rest参数。
(function (a) {}).length /*1*/
(function (a = 5) {}).length /*0*/
(function (a, b, c = 5) {}).length /*2*/
(function (a = 5, b, c) {}).length /*0*/
(function (...a) {}).length /*0 rest参数*/
作用域:
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域;
等初始化结束,这个作用域会消失;
var x = 1;
function f(x, y = x){
console.log(y);
}
/*参数y的默认值等于变量x,调用函数f时,参数形成一个单独的作用域,在这个作用域中,默认值变量x指向第一个参数x,而不是全局变量x*/
f(2);//2
let x = 1;
function f(y = x){
let x = 2;
console.log(y);
}
/*参数y的默认值等于x,调用函数f时,参数 y = x 形成一个单独的作用域,在这个作用域中,变量x本身没有定义,所以指向全局变量x*/
/*函数调用时,函数体内部的局部变量x影响不到默认值变量x*/
f();