一、函数参数的默认值
function log(x,y='world'){
console.log(x,y);
}
log('hello'); //hello world
log('hello',''); //hello
注意:参数是默认声明的,所以在函数体内不能用let或const再次声明
function foo(x=5){
let x=1; //error
const x=2; //error
}
注意:使用参数默认值时,函数不能有同名参数
function foo(x,x,y){..........}
//报错
注意:函数参数是惰性求值(参数默认值不是传值的,而是每次都重新计算默认值表达式的值)
var x=99;
funtion foo(p=x+1){
console.log(p);
}
foo(); //100
x=100; //修改全局作用域下x的值
foo(); //101
注意:参数设置默认值位置应该在尾部
function f(x=1,y){
return [x,y];
}
f(,1); //报错(传递数值前面的参数无法省略)
//除非显性传入undefined (意义不大)
f(undefined,1); //[1,1]
二、函数的length属性
函数的length属性将返回没有指定默认值的参数个数
(function(a){......}).length; //1
(function(a=5){......}).length; //0
注意:rest参数不计入length属性
(function(...args){......}).length; //0
注意:*如果设置了默认值的参数不是尾参数,那么length属性不再计入后面的参数
(function(a=0,b,c){....}).length; //0
(function(a,b=1,c){....}).length; //1
三、函数参数作用域
一但设置了参数默认值,函数进行声明初始化时,参数会形成一个单独的作用域。初始化结束后,作用域就会消失。
var x=1;
function f(x,y=x){
console.log(y);
}
foo(2); //2
解释:调用foo时传递参数x=2,此时y没有传递参数,触发默认值为x,并且参数x,y形成一个单独作用域。在当前作用域下x=2,故y的值是2,而不是全局作用域下x。
let x=1;
function f(y=x){
let x=2;
console.log(y);
}
f(); //1
解释:函数参数触发单独作用域,因为在当前作用域下找不到x的值,向外层(更高层)寻找变量x,故y=1。不是函数体内的x=2。如果最外层找不到该变量,则报错。
如果参数的默认值是一个函数,该函数的作用域也遵守这个规则
let foo='outer'
function bar(func=x=>foo){
let foo='inner';
console.log(func());
}
bar(); //outer
var x=1;
function foo(x,y=function(){x=2;}){
var x=3;
y(); //此时全局下的x的值被修改为2
console.log(x);
}
foo();//3
x;//1(函数参数x)
解释:函数参数x指向全局下的x,即x=1。y的值是匿名函数。在foo函数体中,执行y() 。此时函数y内部的x是指向全局下的x,故此时全局下的x则已经被修改了。函数体输出x,是输出函数体内部的x,而不是全局下的x。
var x=1;
function foo(x,y=function(){x=2;}){
x=3;//此时全局下的x的值被修改为3
y(); //此时全局下的x的值被修改为2
console.log(x);//全局下的x
}
foo();//2
x;//1(函数参数x)
解释:与例子三的区别在于函数foo中的x是指向全局的。
四、严格模式
从ES5开始,函数内部可以设定为严格模式。在ES6中,规定只要函数使用了默认值,解构函数或者扩展运算符,那么函数内部就不能显性设定为严格模式,否则会报错。