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
}
Answer from Ethan Brown on Stack Overflowisn't function a block?
i mean anything between { and } is a block, right?
so function is also designed like that
function(){here}
why isn't this considered a block scope as well?
why ain't the both same?
Videos
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
}
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
- javascript 5 does not use blocked scope it uses chained scope. the main difference is that you cannot access the variable out side of the scope unless you make it global. ES 6 will have blocked scope when you declare a variable with let.
- currently recommended to use var because ES 6 is not fully supported.
I'm not sure you really got your questions answered yet:
Is block scope sometimes the same as function scope? I know function scope is for everything inside a function, but don't get what exactly a block scope is.
Yes, a block scope is sometimes the same as a function scope. Block scope is everything inside a set of braces { a block scope here }. So, at the top of a function's code, a block scope will be the same as a function scope:
function test(x) {
// this is both a block scope and a function scope
let y = 5;
if (x) {
// this is a smaller block scope that is not the same as the function scope
let z = 1;
}
}
For Javascript, is it currently recommended to use let / const instead of var for future maintenance? (This was from Airbnb Style Guide)
let and const are part of the newest ES6 specification and are only implemented in the latest Javascript engines and sometimes in the latest engines they are only enabled with special flags. They are coming to all newer JS engines/browsers, but are not widely deployed yet. Thus, if you are writing Javascript for regular browser consumption across the broad internet, you cannot reliably use let and const yet.
There are some cases where you can safely program with let and const now:
If you are targeting only a specific Javascript engine and you know that it has support for those features (such as a specific version of nodejs or a plug-in only for a specific version of a specific browser).
If you are using a transpiler that will convert your code to code that will run in all browsers. When using a transpiler, you can write your code using the latest features and the transpiler will "dumb it down" so that your code will work in older browsers by using simulations of the newer features.
If you are programming for an environment where you know that let and const are supported, then it is advisable to use them as appropriate. If you declare a variable at the top of your function, then let and var will do the same thing.
If you declare a variable in a smaller scope within the function, then let will be contained within the smaller scope, but var will be hoisted to the top of the function and will have function scope, no matter where it is declared.
The AirBnb Style Guide you linked to is specifically written for an ES6 environment (note there is a separate link for an ES5 version of their style guide). So, that means that they are assuming an ES6 capable environment. That's either because they are targeting a server-side JS engine that they know supports ES6 or because they are using a transpiler that will convert ES6 code into something that will run on an ES5 engine.
A note about transpilers. Before using a transpiler and switching all variable declarations to let within block scopes, it is worth understanding what kind of code the transpiler generates and whether the extra code it generates has any effect on the performance of your application. For example, block scope for let is simulated by creating an inline IIFE which can lead to extra run-time overhead for every block that contains a let statement. I'm not saying this is necessarily a bad thing that should keep you from using a transpiler, but when deciding whether to use a transpiler, I'd suggest that you thoroughly familiarize yourself with what the transpiled code looks like for a variety of ES6 features so you know whether it is the right tool for any job you have or only for some jobs.
So overall i understand the functionality behind block / function scope. But my questions seems more in line with the semantics of it.
Would a function scope not also be a block scope on top of being function scoped? Considering that it is contained within brackets. And variables inside it cannot be accessed from the outside unless passed via callbacks as arguments. The main difference that I can come to in my testing is that you can access variables inside block scope with VAR. But var cannot be used to access variables that are function scoped
const functionScope = () => {
if(x){
const variable = "This variable cannot be accessed outside this block"
var variable2 = "This variable can be accessed outside this block"
// Inside these brackets is block scope
}
const variable = "This variable cannot be accessed outside this block"
var variable2 = "This variable cannot be accessed outside this block"
//inside these brackets is function scope
}