输出为15(在f中,x为10,y为7),具有以下内容:
var x = 5;
function f(y) { return (x + y) - 2};
function g(h) { var x = 7; return h(x) };
{ var x = 10; z = g(f); console.log(z) };
为什么x取第4行而不是第1行的值(为什么不是第3行)?
答案 0 :(得分:5)
var
不阻止作用域,因此最后一行等同于
x = 10; z = g(f); console.log(z)
现在应该更清楚一点,x
的价值在执行 10
之前已更改为f
。
同样重要的是要注意,当函数调用时,评估自由变量,而不是在定义时评估。当然,变量的值可以在函数的定义和函数的调用之间改变,就像在你的例子中一样。
在第三行中,x
是g
的本地,因此完全独立于"外部"变量x
。
另见What is the scope of variables in JavaScript?
一个更简单的示例演示了这种行为:
var x = 5;
function foo() {
console.log(x);
}
x = 10;
foo(); // outputs 10
答案 1 :(得分:3)
var x = 5;
function f(y) { return (x + y) - 2};
function g(h) { var x = 7; return h(x) };
{ var x = 10; z = g(f); console.log(z) };
有点乱,所以让我们把它清理干净:
/* 1 */var x = 5;
/* 2 */
/* 3 */function f(y) {
/* 4 */ return (x + y) - 2
/* 5 */};
/* 6 */
/* 7 */function g(h) {
/* 8 */ var x = 7;
/* 9 */ return h(x)
/* 10 */};
/* 11 */
/* 12 */{
/* 13 */ var x = 10;
/* 14 */ z = g(f);
/* 15 */ console.log(z)
/* 16 */};
这仍然有一些我逐字复制的问题。我所做的就是添加空格。现在我要清理代码,以便表达实际的执行顺序。
// variable and function declaration happens before assignment
// variables are scoped to their containing function,
// or, when no parent function exists, to global scope
var x;
function f(y) {
// cleaned up semicolon usage (lines 4 & 5)
// while JavaScript's automatic semicolon insertion would work
// it's generally better to be explicit about intent
return x + y - 2;
}
function g(h) {
// again separated variable declaration from assignment
// from line 8 above
var x;
x = 7;
return h(x);
}
// removed unnecessary block scope from lines 12 & 16
// variable assignment now can happen after declaration
// x is assigned from line 1 above
x = 5;
// x is subsequently overwritten from line 13 above as
// JS variables don't have block scope
// duplicate var declaration has no effect and is removed
x = 10;
z = g(f);
console.log(z);
现在代码格式正确,很明显x
的值为10
,因为执行顺序会导致x
被覆盖。
答案 2 :(得分:0)
在javaScript中,没有任何内容称为块级范围。它被视为全局变量。现在让我们分析这些陈述及其范围。最初,您已声明 var x = 5; 。然后你定义了两个函数,然后你又定义了 var x = 10; 。请注意,JavaScript将覆盖x的值。现在x在全球范围内是10。
现在你声明了z = g(f);您正在将函数作为参数传递。在g中,你再次声明x为 var x = 7; 。请注意,函数内定义的变量具有比全局作用域中声明的相同变量名更高的优先级,并且变量的当前值仅对此函数可见。在g之外,每个人都知道x是10.但是在g里面,x的值将是7.
现在,你已经返回了h(x);这意味着你将f(y)称为f(7); f仍然知道x在全局范围内是10,并且不知道它是否存在于函数g内部。所以f计算(10 + 7) - 2.因此z的值变为15。
为了澄清,我建议您使用浏览器工具中的调试器。调试每一行并了解范围的工作原理。希望它有所帮助。