-2

i have a global variable x, which has the same name as that of the inner function when i execute the test function it also executes the function which has same as that of the global variable, this function contains assigns value to the variable which has the same name as that of the function, now when in the next line it alerts the value of the x, it alerts 2, but when after the execution of the test function if you alert the x it still alerts 10... y?

eg
var x  =10;      //assigns value 10 to global variable x
function test(){
  function x () {
    x = 2;  //assigns value x
    alert(x);   // x =2
  }
  x();  //calls x
}

test();    //call function test

but if you alert x, then it gives 10... why like this;

and if you do like this

var y  =10;  //assign value 10 to y
function test(){
  function x () {
    y = 2;  //assign value 2 to y
    alert(y);  //alerts y is 2
  }
  x(); //call the function x
}

test();     //call the test function

and if you check y then also it is 2.. what is the difference between the two.. I know the behaviour of the second one.. but have no idea about the first one...

Joseph
  • 682
  • 5
  • 17
  • 1
    Is there a reason why you have variable names matching your function names? – Wild Beard Jan 10 '15 at 19:04
  • 1
    The received wisdom is that you don't even use `i` or `x` but something more meaningful - let alone duplicating the identifiers - how less readable can you get? If you had declared sensible names in the first place you would not have wasted your time with this question - or are you trying to pick holes? – Weather Vane Jan 10 '15 at 19:23

2 Answers2

1

A function declaration does two things:

  1. It declares a new variable in the current scope (with the same name as the function). This is the same as var x.
  2. It creates a function and assigns it to that variable. This is the same as x = function x () { ... } except it is hoisted.

In the first example, the function declaration for x creates a variable x in the scope of test so when you x = 2;, you are overwriting the pointer to the function in x with 2 while leaving the other variable x (which exists in the wider scope and holds the variable 10 alone).

This can be demonstrated:

var x = 10;

function test() {
  function x() {
    x = 2; //assigns value x
  }
  alert("x inside test before calling x(): " + x)
  x(); //calls x
  alert("x inside test after calling x(): " + x)
}

alert("x outside test before calling test(): " + x)
test()
alert("x outside test after calling test(): " + x)

In the second example, the function is called y, so it doesn't create a new x in the narrower scope and x = 2 touches the original x.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • If I replace `test()` with `alert(test))` then I get a string representation of the function body (in Firefox): http://jsbin.com/gicuhayifi/1/edit?html,output - even if that wasn't the case, it wouldn't show that `x` is not assigned to "the function value" since you are looking in the wrong scope. For comparison see: http://jsbin.com/yecuxuceqe/1/edit – Quentin Jan 10 '15 at 19:18
  • In Firefox, the first function's `alert()` informs `2` (not 10). If in `test()` I change `x()` to `return(x())` I get *undefined*. So here, `x` is not assigned to the function value, it references the local `(var) x`, as proven by checking that the global `x==10` still after calling `test()`. – Weather Vane Jan 10 '15 at 19:19
  • If you change `x()` to `return(x())` then you return *the return value of `x()`* and not *the value of `x`*. Since the `x` function doesn't have a return statement, that behaviour is expected. – Quentin Jan 10 '15 at 19:20
  • You implied that `x` (within function `x()`) is assigned to the value of the function `x()` – Weather Vane Jan 10 '15 at 19:20
  • @WeatherVane — There are two different `x`s and they get different values assigned to them at different times. The initial value of the locally scoped `x` is the function `x` (not the return value from calling it, the function itself). – Quentin Jan 10 '15 at 19:23
  • There is no `x` within the `function x`. There is an `x` inside the function `test` and another `x` outside it. The initial value of the `x` inside `test` is the `function x`. – Quentin Jan 10 '15 at 19:23
  • See? just how confusing can you make it? There are not two different `x`s there are *three*. – Weather Vane Jan 10 '15 at 19:25
  • There are two variables called `x`; there is also a function named `x`. The variables are the important ones to focus on as far as questions of scope are concerned. When I've discussed the function, I've explicitly called it out as `function x`. – Quentin Jan 10 '15 at 19:27
  • What are you talking about? *"There is no `x` within the function `x()`"*. Look again: `function x () { x = 2; alert(x); }` – Weather Vane Jan 10 '15 at 20:14
  • @WeatherVane — That `x` is inside `function test`. It is accessible from within `function x` but isn't scoped to `function x`. Since there isn't an `x` scoped to `function x`, the `x = 2` expression reaches outside of `function x` until it finds a scope where there is an `x`. – Quentin Jan 10 '15 at 20:15
  • Whatever - see comments under OP. – Weather Vane Jan 10 '15 at 20:17
  • @WeatherVane — What about them? I'm just explaining what is happening, not claiming that it is good practise to name variables that way. – Quentin Jan 10 '15 at 20:18
  • As I commented earlier, Firefox does not exhibit OP's complaint. – Weather Vane Jan 10 '15 at 20:18
  • @WeatherVane — Firefox behaves exactly as the OP describes. I explained how your tests appear to differ from what the OP wrote and provided extended tests of my own that demonstrate the problem more clearly. – Quentin Jan 10 '15 at 20:20
  • There is an ambiguity in OP's comment "but if you `alert(x)`, then it gives 10". Within `test()` it gives 2, after calling `test()` it gives 10. Within both `test()` functions, x and y behave identically. You say `x=2` assigns that to the function `x()` return value. It doesn't, it is `undefined`. – Weather Vane Jan 10 '15 at 20:27
  • The comments in the OP's source code combined with the statement *in the next line it alerts the value of the x, it alerts 2* **and** the statement *after the execution of the test function if you alert the x it still alerts 10*, combined with the fact that *the last of those statements can only be true if the alert being discussed in one on an additional line at the end of the code example* makes it clear what the OP means. – Quentin Jan 10 '15 at 20:30
  • I did not say "`x=2` assigns that to the `function x()` return value". Nothing can ever be assigned to the return value of anything. I said that `x=2` **overwrites the reference to the `function x` in the variable `x` that is scoped within `function test`**. Nothing ever even looks at the *return value* of anything in any of this code. – Quentin Jan 10 '15 at 20:31
0

The function keyword is similar to var -- they both make the name they define into a local variable. So there are two x variables: one whose scope is outside the test function, the other whose scope is inside the function. Assigning to the inner x has no effect on the outer x.

In your second version, you don't have a var or function declaration for y inside the function, so it accesses the global variable.

For more information, see

What is the scope of variables in JavaScript?

Community
  • 1
  • 1
Barmar
  • 741,623
  • 53
  • 500
  • 612