【 tulaoshi.com - Web开发 】
(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)这个第一篇中间的内容讲得大体都是对的,但是还是搞得太复杂。倒是头尾两句话非常具有典型意义:
引用什么叫闭包?我花了很长时间来弄明白这个概念,但每次以为弄明白的时候,却又会发现其实没搞清楚。
引用这究竟是为什么,我目前还不清楚。但据说ECMA262标准给出了具体的实现方法的我没体力看了,交给大家吧。
暂时没有时间详细解说这些内容,仅把在小麦文章后面的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的影响,可以看这位用scheme实现JS引擎的同志的说法:
引用...But the real subtlety comes in with the
with (dynamically add a computed object value to the runtime environment as a new environment frame) and
eval constructs...
... So outside of a
with, you get normal, efficient lexical scope; inside a
with, you get stupid, slow, dynamic scope...