注意理解:
1、
var x = 1;
function f(x, y = x) {
console.log(y);
console.log(x);//undefined
}
f(2) // 2
2、
let x = 1;
function f(y = x) {
let x = 2;
console.log(y);
}
f() // 1
3、
function f(y = x) {
let x = 2;
console.log(y);
}
f() // ReferenceError: x is not defined
4、
var x = 1;
function foo(x = x) {
// ...
}
foo() // ReferenceError: x is not defined
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域,等到初始化完成,这个作用域就会消失,这种语法在不设置默认参数时是不会出现的。
所以:1、在x为添加默认值,y设置默认值为x,这时这个x在外部作用域已经定义,就会将这个值赋值给y,y=1.同理所以2中y=1。3中x在外部函数并没有被定义,再赋值给y就会报错。4中,参数的执行顺序是从左到右的,所以这句话相当于:let x=x;因此会报错。
再看一个更加复杂的例子:
var x = 1;
function foo(x, y = function() { x = 2; }) {
var x = 3;
y();
console.log(x);
}
foo() // 3
x // 1
上面代码中,函数foo
的参数形成一个单独作用域。这个作用域里面,首先声明了变量x
,然后声明了变量y
,y
的默认值是一个匿名函数。这个匿名函数内部的变量x
,指向同一个作用域的第一个参数x
。函数foo
内部又声明了一个内部变量x
,该变量与第一个参数x
由于不是同一个作用域,所以不是同一个变量,因此执行y
后,内部变量x
和外部全局变量x
的值都没变。
变化其中的一小部分:
var x = 1;
function foo(x, y = function() { x = 2; }) {
x = 3;
y();
console.log(x);
}
foo() // 2
x // 1
如果将var x = 3
的var
去除,函数foo
的内部变量x
就指向第一个参数x
,与匿名函数内部的x
是一致的,所以最后输出的就是2
,而外层的全局变量x
依然不受影响