简述JavaScript的scope机理

小麦正在写《[url=http://www.mikkolee.com/81]作用域链 词法作用域 与 闭包[/url]》系列。这个第一篇中间的内容讲得大体都是对的,但是还是搞得太复杂。倒是头尾两句话非常具有典型意义:
[quote]什么叫闭包?我花了很长时间来弄明白这个概念,但每次以为弄明白的时候,却又会发现其实没搞清楚。[/quote]
[quote]……这究竟是为什么,我目前还不清楚。但据说ECMA262标准给出了具体的实现方法的……我没体力看了,交给大家吧。[/quote]

暂时没有时间详细解说这些内容,仅把在小麦文章后面的comments记录此处。


closure还是比较容易理解的,无非是内部函数可以访问外部的变量。之所以能比较容易的支持closure,也在于JS是使用垃圾回收的,因此不存在函数局部变量生存期的问题——被回收的只是局部变量符号,真正所引用的对象只要还有任何一个地方引用它——无论是直接引用还是像closure那样间接引用,都不会被回收。当然,closure的间接引用也加剧了IE中内存泄露问题,此乃题外话,不赘述。

closure(闭包)、scope chain(作用域链)、lexical scope(词法作用域),三者当然不是一个概念,但是确实是有紧密联系的。具体来说,JS语言是以scope chain的方式来实现lex scope和closure的。所以就算搞不懂scope chain,也不妨碍你使用JS。

1. scope chain是一种实现手段,具体来说,它是一种name lookup的检索机制。

2. lexical scope是一种作用域机制,它很好理解。因为lex scope取决于源代码,所以通常编译器可以进行静态分析来确定每个标识符实际的引用。实际上lexical scope因此也称为static scope。

3. 其实JS并非完全的lexical scope。因为有with和eval这两个特例。所以说JS是lexical scope实际上是说它的scope机制非常接近于lexical scope。

4. 因此JS引擎通常不使用静态分析,而且只使用静态分析是无法实现with的语义的!JS使用类似dynamic scope的技术,区别在于通常dynamic scope的bindings堆栈是全局的,而JS为每个execution context都单独设置一个bindings堆栈,也就是所谓的scope chain。

5. 结论:可以把JS的scope看做一个用scope chain机制实现的近似lexical scope。


Updates:
关于with/eval对于lexical scope的影响,可以看这位[url=http://calculist.blogspot.com/2008/10/updated-javascriptplt.html]用scheme实现JS引擎的同志的说法[/url]:
[quote]...But the real subtlety comes in with the [i]with [/i](dynamically add a computed object value to the runtime environment as a new environment frame) and [i]eval [/i]constructs...
... So outside of a [i]with[/i], you get normal, efficient lexical scope; inside a [i]with[/i], you get stupid, slow, dynamic scope...
[/quote]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值