V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
liberty1900
V2EX  ›  JavaScript

发现了 var 和 let/const 的一个细微差别

  •  
  •   liberty1900 · 240 天前 · 1331 次点击
    这是一个创建于 240 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大多数前端开发者都知道在浏览器里全局对象是 window,这点可以用 Object.is(globalThis, window) 来验证

    如果在浏览器的全局环境下定义一个变量,那么它将被自动挂载到 window 对象上

    var name = "Mike";
    
    console.log(window.name)
    

    但 let 和 const 却不会这样

      let age = 10;
      const sex = "Male";
      console.log(window.age, window.sex)
    
    thinkershare
        1
    thinkershare  
       240 天前   ❤️ 1
    不要用 var 这种垃圾。
    hsfzxjy
        2
    hsfzxjy  
       240 天前 via Android
    是这样的,而且不只这个差别
    rrfeng
        3
    rrfeng  
       240 天前
    var 就是全局变量,千万别用。
    liberty1900
        4
    liberty1900  
    OP
       240 天前
    用惯了了 VS Code ,里面 Cmd + Enter 是 Insert Line Below ,V 站这里直接给我发帖了。。。
    Jirajine
        5
    Jirajine  
       240 天前 via Android   ❤️ 1
    你不用管它有什么区别,你只需要记住 var 是 deprecated ,永远不要使用就行了。
    liberty1900
        6
    liberty1900  
    OP
       240 天前
    let/const 是 block scope 的,我以前理解所谓 block scope 就是用花括号形成的 scope 比如:

    ```javascript
    {
    let age = 10;
    console.log(age); // 10
    }
    console.log(age) // undefined
    ```

    如果我没有显示套上大括号,也就没有了 block scope 但是变量总得有个 scope ,那这个 scope 是不是 global scope 呢?看来我理解错了
    HelloWorld556
        7
    HelloWorld556  
       240 天前   ❤️ 1
    chengxy
        8
    chengxy  
       240 天前
    继续往下,学学 let 和 const 的区别
    Adicwu
        9
    Adicwu  
       240 天前
    这你就得问问变量提升了
    liberty1900
        10
    liberty1900  
    OP
       240 天前
    @liberty1900 一种合理的解释是 let/const 一定是 block scope 的,即使没有显式用花括号声明也是 block scope, 只是这种 scope 是隐式的,而且和 global scope 有区别,不能混为一谈
    liberty1900
        11
    liberty1900  
    OP
       240 天前
    @chengxy 我知道 let 和 const 的区别,也知道 const 的局限性以及如何用 Object.create/Object.definedProperties/Object.seal/Object.freeze 来实现不同程度的不可变
    cmdOptionKana
        12
    cmdOptionKana  
       240 天前
    年轻人真幸福啊,没经历过只有 var 的年代。
    NerbraskaGuy
        13
    NerbraskaGuy  
       240 天前
    这个不算细微吧,let 和 const 被造出来基本就是为了解决 var 这个痛点的
    chnwillliu
        14
    chnwillliu  
       236 天前 via Android   ❤️ 1
    Spec 都定义好了,参见 Execution Context 的 LexicalEnvironment 和 VariableEnvironment 。他俩都是 Environment Record ,但是装的东西不一样,一个负责 let const 声明的东西,一个负责 variable statement ,hoisting 还有 with block 的差异处理都在这里规定好了。

    不光这样,全局还有个特殊的 Environment Record 叫 Global Environment Records, 全局 var 和 function 会变成 global object 的属性的行为就是在这里定义的。
    chnwillliu
        15
    chnwillliu  
       235 天前
    仔细翻了下 Spec ,还是要纠正一下,无论 let const 还是 var ,或者是 function declaration ,class declaration ,这些 identifier 都会在 LexicalEnvironment 中记录,要查找 identifier 也只要查找 LexicalEnvironment 。而 VariableEnvironment 是专门用来管理 variable statement 的,相当于额外放一份,用来处理一些老旧 feature 比如 eval 。

    let/const 和 var 的区别在于在初始进入一个 function 或者 script 的时候,只有 top level 的 let/const 会被加入到 LexicalEnvironment ,而 variable statement 声明的 identifier 和 hoistable declaration 声明的 identifier 比如 function 声明,是会在最开始就全部加入到 LexicalEnvironment 中。

    实例化一个 block declaration 后,需要创建一个新的 LexicalEnvironment 给到当前的 execution context ,后续的 let/const 是加入到这个 LexicalEnvironment 中了的。比如 for ( let i=0; i<10; i++) { let j; } 这里其实创建了 11 个临时 LexicalEnvironment ,for 语句给 i 创建了一个,每次循环会创建另一个新的,放一个 j (然后销毁)。而 var 是不存在这种考量的,无论几个 for 嵌套,都会在最开始就放入顶层的 LexicalEnvironment 。

    不光在开始执行一个 function 会这样处理,在新的 script element ,module 或者 worker 开始执行,都是类似处理。这个顶层 scope 或者说 LexicalEnvironment , 就是 Global Environment ,Module Environment 和 Function Environment 。

    Global Environment 在每个 realm 中只有一个,在 user land 和 globalThis 是等价的,而 var 变量 和 function declaration 的 identifier 能用 globalThis 直接当属性访问也是 Global Environment Record 做的特殊处理,参见 CreateGlobalVarBinding 和 CreateGlobalFunctionBinding 。

    Function Environment 在每次 call 一个 function 的时候都会创建,module 同理,在第一次 import 时创建。

    一个有趣的例子,这个 early error 是如何产生的呢?

    ```
    (function(){

    {

    {
    {
    {
    var b
    }
    }

    let b;
    }
    }

    })()
    ```
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2935 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 09:21 · PVG 17:21 · LAX 02:21 · JFK 05:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.