推荐关注
› Meteor
› JSLint - a JavaScript code quality tool
› jsFiddle
› D3.js
› WebStorm
推荐书目
› JavaScript 权威指南第 5 版
› Closure: The Definitive Guide
Dummy

为什么说JS不支持块级作用域?

  •  
  •   Dummy · Nov 26, 2013 · 9508 views
    This topic created in 4730 days ago, the information mentioned may be changed or developed.
    最近被Boss逼着学习Javascript,让我少看杂七杂八的书,从语法深入。

    《Javascript语言精粹》提到

    “Javascript的代码块语法看起来支持块级作用域,实际上JS并不支持,这个混淆之处可能成为错误之源。”

    有一点无法理解啊,函数作用域不就是块级作用域么,为什么说不支持?
    混淆可能导致什么错误呢?
    17 replies  •  1970-01-01 08:00:00 +08:00
    Sivan
    Sivan
    Nov 26, 2013 via iPhone
    1
    this 容易用错。
    otakustay
    otakustay
    Nov 26, 2013
    2
    函数不是块,在语法中的block是指if/else/for/while语句里2个大括号之间的部分
    xuyiwei
    xuyiwei
    Nov 26, 2013
    3
    是 花括号 {} 跟 java C# 这些用法不一样
    yimity
    yimity
    Nov 26, 2013
    4
    @otakustay 回复的是正确的。
    coffeedeveloper
    coffeedeveloper
    Nov 26, 2013❤️1
    5
    代码说明一切:
    ```
    var a = true;
    if(a){
    var b = 1;
    }
    alert(b) //输出1
    ```
    正常来说如果有块级作用域的话,```alert(b)```应该是输出```undefined```才对。
    Mutoo
    Mutoo
    Nov 26, 2013
    6
    javascript:

    for(var i=0;i<10;i++){
    console.log(i); //0, 1, ..., 9
    }
    console.log(i); //10


    c++:

    for(int i=0;i<10;i++){
    cout<<i<<endl; //0, 1, ..., 9
    }
    cout<<i<<endl; // undeclared variable i
    yemoluo
    yemoluo
    Nov 26, 2013
    7
    赞楼上几位
    teddy1004
    teddy1004
    Nov 26, 2013
    8
    JavaScript 的作用域不太一样,作用域是被定义时候的作用域,而不是执行时的。

    function hello() {
    for (var i = 0; i < 10; i++) { doSomething... }
    }

    console.log(i);

    一般的语言上面的语法就是错误的,因为变量 i 应该已经被销毁了。但是 JS 中就是可以的。
    toctan
    toctan
    Nov 26, 2013
    9
    @teddy1004 这代码明显会报错嘛,由于 JS 的 function scope, i 在函数外不可见,明显会报
    `ReferenceError: i is not defined`

    其实我觉得楼主是在问什么是 block scope 和 function scope
    Ricky123
    Ricky123
    Nov 26, 2013
    10
    @coffeedeveloper 好遗憾,回复没有支持Markdown..
    cyberscorpio
    cyberscorpio
    Nov 26, 2013
    11
    后来的标准里面有个 let 关键字支持这个的块级作用域。
    我在写 Firefox 扩展的时候已然大量使用了。
    Golevka
    Golevka
    Nov 26, 2013❤️2
    12
    历史上, JS中的作用域是由activation object/variable object间的引用关系决定的, 所以只有在创建activation object时才会开启一片新的作用域, 这一动作发生在函数被调用时. (其实javascript能实现lexical scope是因为在declare function时先把parent scope给记下来, 这样每次调用函数时都能在正确的位置(F.[[Scope]])创建新的activation object)

    到了ES5时lexical env这块标准完全重做了, 用独立的environment record的概念来代替原有的object模拟scope的定义, 但是行为上基本还是兼容旧标准, 比如Block的求值规则几乎没变动; 到ES6这儿Block几乎完全重做了, 在进Block时会创建新的declarative environment, let和const的作用域解析就做在这个地方; var为了兼容旧标准在variable environment做名字解析.

    (其实到这里var这个东西就应该被干掉了, 或者至少标记为deprecated免得后人踩坑
    yjsslab
    yjsslab
    Nov 26, 2013
    13
    用 js 写函数式编程的代码就应该问题不大吧.
    teddy1004
    teddy1004
    Nov 26, 2013
    14
    @toctan 吐血。。。没注意写错地方了。。。好丢人
    coffeedeveloper
    coffeedeveloper
    Nov 26, 2013
    15
    @Ricky123 好吧,其实我也想不懂为什么v2不支持markdown- -!
    Dummy
    Dummy
    OP
    Nov 27, 2013
    16
    谢谢楼上的同学,终于明白了,其实这个问题持本质就是 @toctan 同学所说的,我没有把块级作用域和函数作用域弄清楚。
    FrankFang128
    FrankFang128
    Nov 27, 2013
    17
    可以结合 hoisting (变量提升)一起理解 http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1573 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 70ms · UTC 08:53 · PVG 16:53 · LAX 00:53 · JFK 03:53
    ♥ Do have faith in what you're doing.