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

2013-11-26 01:34:20 +08:00
 Dummy
最近被Boss逼着学习Javascript,让我少看杂七杂八的书,从语法深入。

《Javascript语言精粹》提到

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

有一点无法理解啊,函数作用域不就是块级作用域么,为什么说不支持?
混淆可能导致什么错误呢?
7705 次点击
所在节点    JavaScript
17 条回复
Sivan
2013-11-26 02:16:49 +08:00
this 容易用错。
otakustay
2013-11-26 02:18:19 +08:00
函数不是块,在语法中的block是指if/else/for/while语句里2个大括号之间的部分
xuyiwei
2013-11-26 08:33:58 +08:00
是 花括号 {} 跟 java C# 这些用法不一样
yimity
2013-11-26 09:12:06 +08:00
@otakustay 回复的是正确的。
coffeedeveloper
2013-11-26 09:42:48 +08:00
代码说明一切:
```
var a = true;
if(a){
var b = 1;
}
alert(b) //输出1
```
正常来说如果有块级作用域的话,```alert(b)```应该是输出```undefined```才对。
Mutoo
2013-11-26 10:06:52 +08:00
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
GTim
2013-11-26 10:44:52 +08:00
赞楼上几位
teddy1004
2013-11-26 11:12:32 +08:00
JavaScript 的作用域不太一样,作用域是被定义时候的作用域,而不是执行时的。

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

console.log(i);

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

其实我觉得楼主是在问什么是 block scope 和 function scope
Ricky123
2013-11-26 11:51:35 +08:00
@coffeedeveloper 好遗憾,回复没有支持Markdown..
cyberscorpio
2013-11-26 12:01:37 +08:00
后来的标准里面有个 let 关键字支持这个的块级作用域。
我在写 Firefox 扩展的时候已然大量使用了。
Golevka
2013-11-26 12:49:34 +08:00
历史上, 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
2013-11-26 13:22:03 +08:00
用 js 写函数式编程的代码就应该问题不大吧.
teddy1004
2013-11-26 14:50:42 +08:00
@toctan 吐血。。。没注意写错地方了。。。好丢人
coffeedeveloper
2013-11-26 15:04:45 +08:00
@Ricky123 好吧,其实我也想不懂为什么v2不支持markdown- -!
Dummy
2013-11-27 00:26:10 +08:00
谢谢楼上的同学,终于明白了,其实这个问题持本质就是 @toctan 同学所说的,我没有把块级作用域和函数作用域弄清楚。
FrankFang128
2013-11-27 12:53:00 +08:00
可以结合 hoisting (变量提升)一起理解 http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/90615

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX