javascript范围隐私破坏?

时间:2017-03-22 07:10:31

标签: javascript scope

所以我刚刚在javascript项目工作时遇到了一些非常奇怪的事情,这里有一个我很困惑的情况的简单示例:

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

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

当你调用doSomething()时,可以在2nd for循环中访问shouldBePrivate变量。

这不应该是不可能的吗?

2 个答案:

答案 0 :(得分:5)

javascript中的所有局部变量都有函数作用域而不是块作用域(至少在ECMAScript 2015 之前)。这意味着函数内部声明了变量,可用于整个函数。

您所指的是块范围。不幸的是,Javascript中的noblock范围直到ECMA2015。从ECMAScript 2015开始,您可以使用let声明您的变量,这些变量只能在块中引用,并且一旦您从该块中退出就会死亡。

MDN docs says (with examples)

  

块范围规则

     

使用 var

     

使用var声明的变量没有块范围。块引入的变量的范围限定在包含的函数或脚本中,设置它们的效果会持续超出块本身。换句话说,块语句不引入范围。虽然“独立”块是有效的语法,但您不希望在JavaScript中使用独立块,因为如果您认为它们在C或Java中执行类似此类的操作,则它们不会按照您的想法执行操作。对于

example:

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

这会记录2,因为块中的var x语句与块之前的var x语句在同一范围内。在C或Java中,等效代码将输出1。

     

使用let和const

     

相比之下,使用let和const声明的标识符具有块范围:

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.

答案 1 :(得分:2)

你偶然发现了一个叫做吊装的东西。因为所有变量都作用于其包含函数,所以var语句在内部移动到函数的顶部。

这意味着解释器实际上将运行此代码:

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);
    }
}

从ES2015开始,您可以使用let关键字而不是词法作用域的var - 即在块内限定范围,这意味着let shouldBePrivate = 5;将不存在于第一个循环之外。

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);
    }
}