【问题标题】:javascript scope privacy breaking?javascript范围隐私破坏?
【发布时间】:2017-03-22 07:10:30
【问题描述】:

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

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

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

当您调用 doSomething() 时,shouldBePrivate 变量可在第二个 for 循环中访问。

这不应该是不可能的吗?

【问题讨论】:

    标签: javascript scope


    【解决方案1】:

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

    您指的是块范围。不幸的是,直到ECMA2015,Javascript 中的范围都没有。从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.
    

    【讨论】:

    • 哦,哇!我不知道javascript做到了。非常有趣,非常感谢您的解释!
    【解决方案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);
        }
    }
    

    【讨论】:

    • 天哪,这很有趣,我不知道。感谢您的信息!
    猜你喜欢
    • 1970-01-01
    • 2017-11-18
    • 2012-07-09
    • 2016-01-04
    • 2011-03-28
    • 1970-01-01
    • 2013-03-06
    • 2022-01-19
    • 1970-01-01
    相关资源
    最近更新 更多