Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

javascript scope privacy breaking?

So I came across something very odd while working on a javascript project just now and here's a boiled down example of the situation I'm confused about:

function doSomething() {
    for(var d = 0;d < 10;d++) {
        var shouldBePrivate = 5;
    }

    for(var d = 0;d < 10;d++) {
        console.log(shouldBePrivate);
    }
}

When you call doSomething() the shouldBePrivate variable is accessible in the 2nd for loop.

Shouldn't that not be possible?

like image 491
Parad0x13 Avatar asked Mar 22 '17 07:03

Parad0x13


People also ask

What is $scope in JavaScript?

Scope in JavaScript refers to the current context of code, which determines the accessibility of variables to JavaScript. The two types of scope are local and global: Global variables are those declared outside of a block. Local variables are those declared inside of a block.

Can you access the Let variable outside of the block scope?

No, You can't access let variables outside the block, if you really want to access, declare it outside, which is common scope.

Does JavaScript have block scope?

Block Scope Before ES6 (2015), JavaScript had only Global Scope and Function Scope. ES6 introduced two important new JavaScript keywords: let and const . These two keywords provide Block Scope in JavaScript.

What are the valid scopes of a variable in JavaScript?

JavaScript variables have only two scopes. Global Variables − A global variable has global scope which means it can be defined anywhere in your JavaScript code. Local Variables − A local variable will be visible only within a function where it is defined. Function parameters are always local to that function.


2 Answers

All local variables in javascript have function scope and not the block scope (atleast before ECMAScript 2015). Which means that declared variables inside the function , available for whole function.

What you are referring is block scope. Unfortunately noblock scope in Javascript till ECMA2015. From ECMAScript 2015, you can declare your variables with let which can be referred only with in the block and they die as soon as you come out of that block.

MDN docs says (with examples)

Block Scoping Rules

With var

Variables declared with var do not have block scope. Variables introduced with a block are scoped to the containing function or script, and the effects of setting them persist beyond the block itself. In other words, block statements do not introduce a scope. Although "standalone" blocks are valid syntax, you do not want to use standalone blocks in JavaScript, because they don't do what you think they do, if you think they do anything like such blocks in C or Java. For

example:

var x = 1;
{
  var x = 2;
}
console.log(x); // logs 2

This logs 2 because the var x statement within the block is in the same scope as the var x statement before the block. In C or Java, the equivalent code would have outputted 1.

With let and const

By contrast, identifiers declared with let and const do have block scope:

let x = 1;
{
  let x = 2;
}
console.log(x); // logs 1
The x = 2 is limited in scope to the block in which it was defined.
like image 111
Suresh Atta Avatar answered Oct 10 '22 20:10

Suresh Atta


You've stumbled upon something called hoisting. Because all variables are scoped to their containing function, var statements are internally moved to the top of the function.

That means that the interpreter will actually be running this code:

function doSomething() {
    var shouldBePrivate;
    var d;
    for(d = 0;d < 10;d++) {
        shouldBePrivate = 5;
    }

    for(d = 0;d < 10;d++) {
        // now it's easy to see why this works
        console.log(shouldBePrivate);
    }
}

As of ES2015, you can use the let keyword instead of var which is lexically scoped - i.e. scoped within blocks, meaning that let shouldBePrivate = 5; will not exist outside the first loop.

function doSomething() {
    for(let d = 0;d < 10;d++) {
        let shouldBePrivate = 5;
    }

    for(let d = 0;d < 10;d++) {
        // Reference Error for shouldBePrivate 
        console.log(shouldBePrivate);
    }
}
like image 29
iblamefish Avatar answered Oct 10 '22 20:10

iblamefish