11

I have been programming in JavaScript for a few months mostly using jQuery. I understand closures and I have used them, however, I still can’t understand what is the difference between function level scope and block level scope in other languages such as C#. I have been trying to teach myself with no result on that subject. Could somebody explain me with some simple examples?

3 Answers 3

22

Prior to ES6 (the current version of JavaScript), JavaScript had only function level scope. That is, the following:

function foo() {
    console.log('before block: ' + bar);      // prints 'undefined'
    if(true) {
        var bar = 1;
        console.log('inside block: ' + bar);  // prints 1
    }
    console.log('outisde block: ' + bar);     // prints 1
}

Is exactly equivalent to:

function foo() {
    var bar;
    console.log('before block: ' + bar);      // prints 'undefined'
    if(true) {
        bar = 1;
        console.log('inside block: ' + bar);  // prints 1
    }
    console.log('outisde block: ' + bar);     // prints 1
}

(As a matter of fact, what I've just shown is called "hoisting", which is exactly what JavaScript does: all variable declarations are hoisted to the top of the function; assignments are left where they are.)

In contrast, languages like C# have block level scope. This would result in a compile error:

public void Foo() {
    if(true) {
        var foo = 1;
        Console.WriteLine("inside block: " + foo);
    }
    Console.WriteLine("outside block: " + foo);  // WILL NOT COMPILE
}

But you can have this:

public void Foo() {
    var foo = 1;
    if(true) {
        foo = 2;
        Console.WriteLine("inside block: " + foo);  // prints 2
    }
    Console.WriteLine("outside block: " + foo);     // prints 2
}
Sign up to request clarification or add additional context in comments.

11 Comments

I think I got it here. Thanks.
Glad it was helpful, Dimt. If you feel this was the best answer, could you mark it as accepted, pelase?
@EthanBrown You've misread the OP's comment - a variable declared in an inner function is not accessible to the outer scope.
That's correct, Alnitak, good catch. Dimt, what you said ("In JS if a variable is dedlcared in an inner function, the enclosing function has access to that variable") is NOT true; a variable declaration anywhere inside a function will mask a variable of the same name declared in the outer scope.
@uzay95, I'm not sure I understand your question, but var bar = 1 is an initialization AND a declaration. The declaration will be hosted, and the initialization won't. Also, I don't recommend w3schools as a learning resource; they excel at SEO but not much else.
|
5
function scopeTest() {

/* consider this simple for loop
    to be the "block" that we were
    talking about earlier
*/
for (var i = 0; i <= 5; i++)
{
  var inFor = i; 
}

alert(inFor);  // what happens here?

}


// call the function defined above
scopeTest( );

In the code above, we have a variable called inFor that was declared in a for loop. We then try to access the inFor variable outside the for loop in the alert statement.

If the code above does not alert anything then we know it's because Javascript uses block scope. In a block scoped language, the variable inFor will not be visible outside of the for loop. This means that if Javascript is a block scoped language, then the call to "alert(inFor);" will not recognize the inFor variable, and nothing will be output to an alert box.

But, the code above actually outputs a "5", which means that the inFor variable does exist outside of the for loop, which must mean that Javascript does NOT have block scope. And there is our answer - Javascript does not have block scope.

function scopeTest() {

var x = 2;

//this is always true:
if(x == 2)
{
  var y = 15;
  for (var i = 0; i <= 5; i++)
  {
    var inFor = i; 
  }
} 

  console.log(y); // y is defined, prints 15   
  console.log(i);  // i is defined, prints 6
  console.log(inFor);  // inFor is defined, prints 5

}

You can see in the code above that the variables y, i, and inFor are declared either inside the if statement or inside the for loop. But, even though those variables are declared inside those separate "blocks", they are still visible to the rest of the function. This is because all of those variables are declared inside one function - which is what function scope is all about.

Block scope vs Function scope

So, if Javascript doesn't use block scope, then what kind of scope does it use?

Well, Javascript uses something called function scope.

Basically, the difference between function scope and block scope is that in a language that uses function scope, any variables declared within a function are visible anywhere within that same function. But with block scope, the visibility of variables is confined to any given block (whether it's an if statement, where/for loop, etc) enclosed by curly braces.

http://www.programmerinterview.com/index.php/javascript/javascript-block-scope/ http://www.programmerinterview.com/index.php/javascript/javascript-function-scope/

    {
     here you can't access both a and b
     var a=1
     here you can access only a
        {
        here you can access only a
        var b=3
        here you can access both a and b
        {
        here you can access both a and b
        }
        here too you can access both a and b
        }
        here you can access only a
        }
       here you can't access both a and b

4 Comments

So in block level scope the iteration variable in For loop is not accessible in outer block whereas in function level scope it is visible in outer function. Is that correct ?
no, see {} this is boundary of variable, so you can't access any variable out side this boundary... note... inside of {} this boundary contains declaration of variable...
see my updated answer... i hope you can understand now
I'm gonna try those examples for practice, That should help me. Thanks.
1

To continue with @Ethan Brown's answer, if we use let or const instead of var, we get "referenceError" because let and const are block-scoped.

function foo() {
    console.log('before block: ' + bar);      // ReferenceError: bar is not defined
    if (true) {
        let bar = 1;                          // bar is not let and not var
        console.log('inside block: ' + bar);  // prints 1
    }
    console.log('outisde block: ' + bar);     // ReferenceError: bar is not defined
}

Just wanted to make the answer complete.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.