Javascript:为什么对闭包变量的访问可能会很慢

时间:2012-02-12 12:56:42

标签: javascript performance functional-programming closures interpreter

最近我读过这篇文章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 快,但是如果iterpreter写得正确(没有动态范围 - 就像链式哈希表查找...)速度差应该只是微不足道的。或者不是?

1 个答案:

答案 0 :(得分: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 Edition 262第3版。 ECMAscript第5版在那里有一些根本性的变化。