Javascript:为啥访问闭包变量可能很慢
Posted
技术标签:
【中文标题】Javascript:为啥访问闭包变量可能很慢【英文标题】:Javascript: why the access to closure variable might be slowJavascript:为什么访问闭包变量可能很慢 【发布时间】:2012-03-04 04:08:39 【问题描述】:最近我读到了这个performance guide Let's make the web faster,对“避免使用闭包的陷阱”的建议感到困惑(好像这些建议是为变量范围是动态的 CommonLisp 用户提供的):
var a = 'a'; function createFunctionWithClosure() var b = 'b'; return function () var c = 'c'; a; b; c; ; var f = createFunctionWithClosure(); f();
在调用
f
时,引用a
比引用b
慢,后者比引用c
慢。
很明显,引用局部变量 c 比 b 快,但是如果正确编写了迭代器(没有动态范围 - 类似于链式哈希表查找..)速度差异应该只是微不足道的。还是不行?
【问题讨论】:
【参考方案1】:你是对的。现代 JS 引擎将优化 scope chain lookup
和 prototype chain lookup
很多。意思是,AFAIK 引擎试图在下面保存某种带有访问节点的哈希表。
这仅在没有eval()
(显式或隐式,例如setTimeout
)或try-catch
子句或a with statement
调用时才有效。由于这种结构,解释器无法确定如何访问数据,它需要“回退”到经典的scope chain lookup
,这实际上意味着,它必须爬过所有父上下文variable / activation objects
并尝试解决搜索到的变量名。
当然,对于位于“远离”查找处理开始位置的对象/名称,此过程将花费更多时间。这反过来意味着,访问global object
上的数据总是最慢的。
在您的 sn-p 中,a
的查找过程如下所示
anonymous function -> Execution Context -> Activation Object (not found)
anonymous function -> Execution Context -> [[ Scope ]]
- createFunctionWithClosure
- global scope
createFunctionWithClosure -> Activation Object (not found)
global scope -> Variable Object (found)
所描述的查找过程适用于 ECMAscript Edition 262 第 3 版。 ECMAscript 第 5 版有一些根本性的变化。
【讨论】:
为了长寿(和我的好奇心),您能描述一下它在 v5 中的变化吗? 那么如果我在匿名函数内部做var d = eval("this");
,作用域链查找将爬取所有上下文以获取a
的引用?还是只是将this
分配给d
?
@headacheCoder:如果该代码在某种“老式”浏览器中运行,这是很有可能的。然而,你实际上不应该做出如此糟糕的声明:) 尖端浏览器甚至可以使用eval
优化事物,甚至可能依赖于strict mode
。但是这些浏览器无论如何都遵循 ES5 规范。以上是关于Javascript:为啥访问闭包变量可能很慢的主要内容,如果未能解决你的问题,请参考以下文章