Javascript scoping of variables

百般思念 提交于 2019-12-02 13:15:27
Felix Kling

vars are not blocked scoped, so the last line is equivalent to

x = 10; z = g(f); console.log(z)

It should be clearer now that the value of x was changed to 10 before f was executed.
It is also important to note that free variables are evaluated when a function is called, not when it was defined. And of course the value of a variable can change between the definition of a function and the call of the function, just like in your example.

In the third line, x is local to g and therefore is completely independent from the "outer" variable x.

See also What is the scope of variables in JavaScript?


A much simpler example that demonstrates this behavior would be:

var x = 5;
function foo() {
  console.log(x);
}
x = 10;
foo(); // outputs 10
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) };

is a bit of a mess, so let's clean it up:

/*  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 */};

This still has a number of issues which I copied verbatim. All I did was add whitespace. Now I'm going to clean up the code so that it expresses the actual execution order.

// 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);

Now that the code is properly formatted, it's immediately clear that x will have a value of 10 because the execution order leads to x being overwritten.

In javaScript, there is nothing called block level scope. It is treated same as global variable. Now let's analyze these statements and their scope. Initially, you have declared var x = 5;. Then you have defined two functions and then again you have defined var x = 10;. Please note that JavaScript will override the value of x. Now x is 10 globally.

Now you have declared z = g(f); You are passing a function as a parameter. Inside g, you have declared x again as var x = 7;. Please note that the variable defined inside a function has the higher preference than the same variable name declared in the global scope and also the current value of the variable is visible only to this function. Outside g, everyone knows that x is 10.But inside g, value of x will be 7.

Now, you have returned h(x); this means you are calling f(y) as f(7); f still knows that x is 10 globally and doesn't have any idea whether it even existed inside function g. So f computes (10 + 7) - 2. Hence the value of z becomes 15.

For clarification, I would recommend you to use the debugger present in the browser tools. Debug each line and understand how the scope works. Hope it helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!