访问闭包变量与对象变量的速度

时间:2013-12-22 22:44:30

标签: javascript closures

请考虑以下代码:

var xx=1;
var ff=function(){
  return xx+1;
}
ff();    

var gg=function(){
  return gg.xx+1;
}
gg.xx=1;
gg();

这两种方法之间是否应该有明显的性能差异?在我看来,ff函数应该执行得更快,因为它只引用一个变量,而gg函数引用两个变量。我正在开发一款游戏,并希望尽可能地利用各种速度技巧。

1 个答案:

答案 0 :(得分:3)

有人问many times before。这里唯一的区别是这两个例子通常都不会被称为闭包,它们是变量和属性解析的简单例子。

以下情况:

var xx = 1;
var ff = function(){
  return xx + 1;
}

然后在函数内,首先必须在局部变量对象上解析 xx ,然后在作用域链上解析。所以这至少是两次查找。

以下情况:

var gg = function(){
  return gg.xx + 1;
}
gg.xx = 1;

在函数中, gg 必须以与第一种情况完全相同的方式解析(即在局部变量对象上,然后在范围链上),这也是两次查找。找到 gg 后,必须搜索其属性find xx ,这可能涉及多次查找。

鉴于上述情况,假设第一个更快是合乎逻辑的。

当然,这只是一个合乎逻辑的演绎,性能可能实际上与此相反。在某些浏览器中,无论范围链的长度如何,全局变量查找都比本地更快。去图。

可以肯定的是,不同浏览器的性能会有所不同,无论它采用何种方式。这样的性能调整(如果有任何性能优势)正在边缘播放,应该被视为过早优化。

修改

要将其编码为闭包需要类似的内容;

var gg = (function() {
  var g;
  return function() {
    gg = function() {
      return g.xx + 1; // Here is the closure
    }

    if (typeof g == 'undefined') {
      g = gg;
    }

    if (typeof g.xx == 'undefined') {
      g.xx = 1;
    }

    return g();
  }
}());

因为 gg 在IIFE完成之前没有值,所以只能在该点创建闭包,只能在函数第一次运行时才能分配值。 / p>

请注意, g 仍然必须在局部变量对象上解析,然后在作用域链上解析,因此仍然需要两次查找并且没有来自闭包的增益(至少没有逻辑增益)。

编辑2

关于闭包只是要明确:

var xx = 1;
var ff = function(){
  return xx + 1;
}

技术上 形成一个闭包,但不是值得认识的。标识符 xx 在范围链上解析,当某些外部执行上下文完成时,范围链上没有可由 ff 访问的变量。所以闭包只存在于函数所用的时间,因此并不比词法范围更显着。

相反:

var ff = (function() {

  var closureVariable;

  // This "inner" function has a closure with closureVariable
  // If value is undefined, get (return) the value. Otherwise, set it
  return function(value) {
    if (typeof value == 'undefined') {
      return closureVariable;
    }
    closureVariable = value;
  };
}());

在这种情况下, ff 可以独占访问 closureVariable ,这是一个在创建它的函数完成后仍然可以访问的变量:

// set the value
ff('foo');

// get the value
console.log(ff());  // foo

closureVariable 只能由 ff 访问(与全局变量不同),并且会持续多次调用(与局部变量不同)。闭包的这个特性允许它们emulate private members

另一个特性是许多函数可以对同一个变量进行闭包(或priveliged访问),从而模拟一种继承。