作用域
一旦设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
var x=1;
function f(x,y=x){
console.log(y); //2
}
f(2);
</script>
</head>
<body>
</body>
</html>
上面代码中,参数y
的默认值等于变量x
。调用函数f
时,参数形成一个单独的作用域。在这个作用域里面,默认值变量x
指向第一个参数x
,而不是全局变量x
,所以输出是2
。
再看下面的例子。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo</title>
<script src="js/traceur.js"></script>
<script src="js/bootstrap.js"></script>
<script type="text/traceur">
let x=1;
function f(y=x){
let x=2;
console.log(y); //undefined
}
f();
</script>
</head>
<body>
</body>
</html>
f
调用时,参数y = x
形成一个单独的作用域。这个作用域里面,变量x
本身没有定义。函数调用时,函数体内部的局部变量x
影响不到默认值变量x
。所以出现undefined.
function f(y=x){
let x=2;
console.log(y); //undefined
}
f();
下面这样写,其结果也是undefined。
var x=1;
function foo(x = x){
console.log(x); //undefined
}
foo();
上面代码中,参数x = x
形成一个单独作用域。这个作用域里面,变量x
本身没有定义。所以出现undefined.
如果参数的默认值是一个函数,该函数的作用域规则。请看下面的例子。
let foo='outer';
function bar(func = () => foo){
let foo = 'inner';
console.log(func()); //inner
}
bar();
bar
的参数func
的默认值是一个匿名函数,返回值为变量foo
。函数参数形成的单独作用域里面,定义了变量foo
,所以foo
指向内层的局部变量foo
,因此输出inner
。
如果写成下面这样,则输出为outer
let foo='outer';
function bar(func = () => foo){
// let foo = 'inner';
console.log(func()); //outer
}
bar();
上面代码中,匿名函数里面的foo
先是指向函数内层寻找,但是函数内层并没有声明变量foo,于是指向函数外层寻找,因此输出outer。
下面是一个更复杂的例子。
var x=1;
function foo(x,y=function() { x = 2;}){
var x=3;
y();
console.log(x); //2
}
foo();
var x=1;
function foo(x,y=function() { x = 2;}){
var x=3;
y();
console.log(x); //2
}
foo(5);
上面代码中,函数foo
的参数形成一个单独作用域。这个作用域里面,首先声明了变量x
,然后声明了变量y
,y
的默认值是一个匿名函数。匿名函数内部声明了变量x=2
,函数foo
内部又声明了一个内部变量x
,该变量与第一个参数x
由于不是同一个作用域,所以不是同一个变量,因此执行y
后,内部变量x
和外部全局变量x
的值都没变。
var x=1;
function foo(x,y=function() { x = 2;}){
x=3;
y();
console.log(x); //2
}
foo();