10

The code below is JavaScript code. I am trying to understand function scope in JavaScript and following the article over here. I am reproducing the code below -

var cow = "purple"; // just a random cow

var f = function (x) {
    var r = 0;
    cow = "glue";
    if (x > 3) {
        var cow = 1; // a local variable
        r = 7;
    }
    return r;
};

var z = f(2);
alert(cow); // returns purple

I don't quite understand why the string "purple" is alerted. The line cow = "glue"; should set the value of the cow variable to "glue". If I remove the if block, and then alert cow in the last statement, I see that the string "glue" is alerted.

When f(2) is called, the if code block is not entered and nothing in it gets executed, so why do I see different results ? i.e why does alerting cow in the last statement return the string "purple" now ?

4 Answers 4

9

Variable declarations inside functions are always hoisted to the top. So your code is actually:

var f = function (x) {
    var cow, r;
    r = 0;
    cow = "glue";
    if (x > 3) {
        cow = 1; // a local variable
        r = 7;
    }
    return r;
};

Inside the function you're always assigning to the local cow, never the global.

Sign up to request clarification or add additional context in comments.

3 Comments

I think you mean var cow,r there, not var f,r
@ben336 Yes, I fixed that a while ago. Maybe your browser didn't get the edit notification? The websocket thing fails sometimes...
yeah see it now. Working with a spotty network connection today. Also didn't see that other people had answered till I posted mine.
5

The two things to understand here are that Javascript variables are hoisted to the top of their scope, and javascript does not have block scope.

So

  1. All variables in a scope are considered declared at the beginning of the scope
  2. an if statement does not create a new scope.

So your example is equivalent to

var cow = "purple"; // just a random cow

var f = function (x) {
    var cow, r = 0;
    cow = "glue";
    if (x > 3) {
        cow = 1; // a local variable
        r = 7;
    }
    return r;
};

var z = f(2);
alert(cow); // returns purple

The var declaration in the if statement is hoisted to the top. At that point all cow references within the function refer to the local variable cow, rather than the cow from the outer scope.

6 Comments

there is no var in front of cow = glue in the tutorial, i dont know if that is an error by the author
no its not an error necessarily, if the point is to show how js scope works. declaring a var in an if statement is bad practice because its confusing, but its not "wrong"
+1 for pointing out that the if block does not create a new scope, this may very well be the source of the OP misunderstanding.
@bfavaretto oops. I can't even blame that on the websockets :)
Block scope coming soon, however. See the JS 'let' keyword. Honestly though, I never missed it.
|
4

Javascript does not have block scope (except in catch blocks).
All var statements are hoisted to the top of the containing function.

Therefore, cow refers to the local variable anywhere in the function, even if the if never executes.

1 Comment

Actually, not even catch blocks have their own scope (variable environment). See Why do catch clauses have their own lexical environment? for details
4

You didn't really read that article, did you? It explicitly states

Does cow get turned into "glue" when you call f(2)? No, cow is safe in the above code because the var cow declaration inside the if block applies to the entire function. It means that cow is a local variable for the entire function.

However, when you remove the if block you also remove the variable declaration inside it, and the assignment will target the global variable.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.