我以为我理解了范围

时间:2010-07-27 15:43:05

标签: javascript

有人可以告诉我为什么'x'的最后一次记录等于0而不是1.我想是因为它在一个函数之外声明它具有全局范围然后在函数中它的值设置为1并且该值将因为它是全球性的吗?我知道函数内部的第一个'x'值是全局的,因为没有var关键字声明的任何变量都成为window对象的属性。非常感谢

var x = 0; //global variable

function y(){
  x = 1;
  log("1. %n ", x);//1. 1

  var x = 2;
  log("2. %n ", x);//2. 2
}

y();
log("3. %n ", x);//3. 0

3 个答案:

答案 0 :(得分:6)

var语句是提升的主题,当你的代码被评估时,它实际上是这样的:

var x = 0; //global variable
function y(){
  var x; // local!!

  x = 1;
  log("1. %n ", x);//1. 1

  x = 2;
  log("2. %n ", x);//2. 2
}

y();
log("3. %n ", x);//3. 0

在执行y之前,设置了一个新的执行上下文,并且在执行该函数之前发生了Variable Instantiation进程

这就是为什么JSLint每个函数只推荐一个var语句,以便类似于实际发生的事情的原因之一。

答案 1 :(得分:5)

函数内部的变量x是在执行函数时立即创建的,而不仅仅是在到达variable statement的行时:

  

如果变量语句出现在 FunctionDeclaration 中,则变量在该函数[...]中使用函数局部范围定义。输入执行范围时会创建变量。 [...]变量在创建时初始化为 undefined 。 [...]

在第一个作业之前添加x来电时,您可以看到undefined最初是log

function y(){
  log("0. " + x);//0. undefined
  x = 1;
  log("1. " + x);//1. 1
  var x = 2;
  log("2. " + x);//2. 2
}

这意味着函数内的两个赋值都引用函数局部作用域中的x而不是全局作用域中的x

答案 2 :(得分:1)

认为,但无法通过ecmascript规范确认,在函数定义时扫描“var x = 2”行,并且“x”的本地范围适用于整个函数,而不仅仅是“var x”行在函数中的位置。

这是一个更简单的测试用例(通过jsdb测试):

js>x = 0;
0
js>function foo(k) { x=k; }
js>function bar(k) { var x=k; }
js>function baz(k) { x=k; var x=2; }
js>foo(1)
js>x
1
js>bar(2)
js>x
1
js>baz(3)
js>x
1

你会注意到,影响全局“x”的唯一函数是foo()。函数bar()显然只影响局部x。但函数baz()也只影响局部x。您会认为赋值x=k;会影响全局x,因为它发生在“明确影响局部变量x的下一个语句var x = 2;之前”。但我很确定如果你在函数中执行var x,解释器会看到它并将其应用于在该范围内的所有使用x。与你的情况相同。