在javascript中关闭重新编译

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (12)

假设我们有这个代码(暂时忘记原型):

function A(){
  var foo = 1;
  this.method = function(){
    return foo;
  }
}
var a = new A();

是每次运行函数A时重新编译的内部函数?或者更好(以及为什么)这样做:

function method = function(){ return this.foo; }
function A(){
  this.foo = 1;
  this.method = method;
}
var a = new A();

还是JavaScript引擎足够聪明,不会每次都创建一个新的“方法”函数?特别是Google的v8和node.js。

此外,关于何时使用哪种技术的一般建议值得欢迎。在我的具体例子中,它确实适合我使用第一个例子,但我知道外部函数将被实例化很多次。

提问于
用户回答回答于

根据我的理解,它不是“编译”函数的问题,因为它每次执行时都有不同的“范围”。

您使用的第二种方法始终具有method相同的范围。

第一个方法放在函数调用method的范围内A()。因此,该范围内的任何信息(var foo函数参数等)都存储在该函数范围的该实例中。因此,每次都会引用相同的函数代码,但它将处于不同的范围内(因此也是不同的“对象”)。

用户回答回答于

是的,您正在A对象的每个实例化处创建一个新的Function对象。你可以证明这一点如下:

function A(){
  var foo = 1;
  this.method = function(){
    return foo;
  }
}
var a = new A();
var b = new A();
alert(a.method == b.method); // Returns false; two different Function objects

如果要重用相同的Function对象,请将该方法设置为原型的属性,而不是实例。

function B() {
  this.foo = 1;
}

B.prototype.method = function() {
  return this.foo;
}

var a = new B();
var b = new B();
alert(a.method == b.method); // Returns true; it's the same Function object

据我所知,除了在JavaScript对象中创建私有变量之外,没有理由去做第一个版本。在最初的例子中,foo是私人的。没有任何东西可以直接从对象外部访问它。不幸的是,当你使用这种技术实例化大量对象时,它可能会影响性能和内存占用。

在我的代码中,我使用命名约定来区分“公共”和“私有”属性。我将私有属性的下划线命名为第一个字符。所以如果我看到类似的东西myObject._someMethod(),我知道有什么不对。

Edit2:从http://code.google.com/apis/v8/design.html开始,我认为V8会在创建包含method属性的隐藏类时编译一次闭包。

扫码关注云+社区