5

最近我读到这个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编写正确(不带动态范围界定 - 像链式散列表查找。)的转速差应该只有边缘。或不?

回答

4

你说得对。现代JS引擎将优化scope chain lookupprototype 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版有一些根本性的变化。

+0

对于长寿(和我的好奇心),你能描述它在v5中的变化吗? – Hogan 2012-02-12 14:02:14

+0

因此,如果我会在var匿名函数中使用'var d = eval(“this”);'范围链查找将抓取所有上下文以获取'a'的引用?或者只是将'this'分配给'd'? – headacheCoder 2012-04-23 09:21:23

+0

@ headacheCoder:如果代码在某种“旧式”浏览器中运行,那么这很有可能。但是,实际上你绝对不应该做这样一个可怕的声明:)尖端的浏览器甚至可以使用'eval'来优化事物,甚至可能依赖于'严格模式'。但是这些浏览器无论如何都要遵循ES5规范。 – jAndy 2012-04-23 09:27:38

相关问题