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?
问题:
回答1:
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
}
回答2:
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