Javascript:为什么访问闭包变量可能会很慢
问题描述:
最近我读到这个performance guide Let's make the web faster,并被“避免陷阱与封闭”的建议困惑(如果这些建议是给变量范围是动态的CommonLisp用户):Javascript:为什么访问闭包变量可能会很慢
var a = 'a'; function createFunctionWithClosure() { var b = 'b'; return function() { var c = 'c'; a; b; c; }; } var f = createFunctionWithClosure(); f();
当调用
f
,引用a
比引用b
,这是比参考c
慢慢。
这是相当明显的是,引用局部变量Ç比b更快,但如果iterpreter编写正确(不带动态范围界定 - 像链式散列表查找。)的转速差应该只有边缘。或不?
答
你说得对。现代JS引擎将优化scope chain lookup
和prototype chain lookup
。意思是说,AFAIK引擎会在下面存储一些带有访问节点的哈希表。
这仅如果没有eval()
(显式或隐式地,例如setTimeout
)或try-catch
条款或a with statement
调用的工作原理。由于这样的结构,解释器不能确定如何访问数据,它需要“回退”到经典scope chain lookup
这意味着它必须爬过所有父上下文variable/activation objects
并尝试解析搜索到的变量名称。 当然,这个过程将花费更多时间来处理查找处理开始处的“远处”的对象/名称。这意味着,访问global object
上的数据将始终是最慢的。
在你的代码段,用于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第四版262第三版。 ECMAscript第5版有一些根本性的变化。
对于长寿(和我的好奇心),你能描述它在v5中的变化吗? – Hogan 2012-02-12 14:02:14
因此,如果我会在var匿名函数中使用'var d = eval(“this”);'范围链查找将抓取所有上下文以获取'a'的引用?或者只是将'this'分配给'd'? – headacheCoder 2012-04-23 09:21:23
@ headacheCoder:如果代码在某种“旧式”浏览器中运行,那么这很有可能。但是,实际上你绝对不应该做这样一个可怕的声明:)尖端的浏览器甚至可以使用'eval'来优化事物,甚至可能依赖于'严格模式'。但是这些浏览器无论如何都要遵循ES5规范。 – jAndy 2012-04-23 09:27:38