2015-05-27 63 views
7

我知道有类似的问题,但我想看看这些答案在新的Javascript引擎中优化后是否仍然有效。构造函数内部的函数vs原型

在我看来,如何定义构造函数内部最大的好处是,你可以很容易地避免不必知道“这”关键字的值:

var Person = function() { 
    var self = this; 
    self.firstName = null; 
    self.lastName = null; 
    self.fullName = function() { 
    return self.firstName + self.lastName; 
    }; 
}; 

这种方法是通过淘汰赛Managing 'this'建议。这是一个很大的优势,尤其是当代码被许多开发人员修改时,因为它非常易于理解和使用。

另一种方法是使用对象的原型:

var Person = function() { 
    this.firstName = null; 
    this.lastName = null; 
}; 
Person.prototype.fullName = function() { 
    return this.firstName + this.lastName; 
}; 

在这种情况下,有性能上的优势,因为功能的对象将被创建一次。然而,我对它的主要问题是处理'this'关键字可能会很复杂。上面的例子非常简单,但是如果你有事件处理程序,forEach调用,jQuery each()调用,方法是从不同的上下文调用等等,很容易使用这个。

当然,如果你明白'这个'是如何工作的并且知道如何调用方法,那么你不应该有太多问题。但是,根据我的经验,这需要时间并且很容易出错,特别是当代码由许多开发人员制作时。

我知道像V8这样的新JS引擎正在将优化应用于通过创建隐藏类来在构造函数中声明函数的情况:How the V8 engine works?

所以我的问题是,鉴于这些由新的JS引擎完成的优化以及必须处理'this'关键字的复杂性,使用基于原型的方法仍然有意义吗?通过使用将所有内容放入构造函数的方法,我会失去什么?

UPDATE 1:

我只是做了镀铬的微基准测试(版本42)。我使用构造函数中的函数和原型中的函数创建1M对象。这是两个变量,三个功能非常简单的对象,结果是这样的:

​​

听起来即使这些优化的V8仍然是73%的速度。然而,这是一个微型基准。不知道这是否会在真实世界的应用程序中有很大的不同。

更新2:

我也看了看内存消耗有很大的差异,以及。对于函数内部构造:

Shallow size: 64,000,120 
Retained size: 336,001,128 

原型功能:

Shallow size: 40,000,000 
Retained size: 40,000,000 

隐藏类要么优化都不是好还是我失去了一些东西有关。我使用V8建议的单态代码(没有参数的构造函数),但不知道我是否做错了什么。

更新3:

这里是测试我做过万一有人能指出了有什么不对的链接:http://jsperf.com/dg-constructor-vs-prototype

+0

FWIW,我加了3次测试的情况下,“POJO”不使用原型或“新”的关键字,它只是创建了公共方法和私有变量的对象。它的性能与构造器的例子相当。无论哪种方式,尽管增加了复杂性,原型方法仍然更快。 http://jsperf.com/dg-constructor-vs-prototype/2 –

+0

谢谢斯科特。是的,现在听起来最有效的方式就是使用原型。这是一种耻辱,因为我喜欢将“this”分配给“自我”的简单性,并确保“自我”指向对象,而不必去思考“this”指向什么。 – dgaviola

+0

是的,我完全同意。对于简单的对象(没有继承),使用'prototype'只不过是一个微观优化,缺点是必须认真理解和管理'this'的使用。 –

回答

3

我执行快速测试。如果你在构造函数中声明了函数,那么即使在优化之后,两个对象实例也有不同的函数实例。然而,对于原型,您只有一个解释性能差异的函数实例。

var Person = function() { 
 
     var self = this; 
 
     self.firstName = null; 
 
     self.lastName = null; 
 
     self.fullName = function() { 
 
      return self.firstName + self.lastName; 
 
     }; 
 
    }; 
 

 
    Person.prototype.fullName2 = function() { 
 
     return this.firstName + this.lastName; 
 
    }; 
 

 
    var a = new Person(); 
 
    var b = new Person(); 
 

 
    console.log(a.fullName == b.fullName); // returns false 
 
    console.log(a.fullName2 == b.fullName2); // returns true

+0

是的,我用我做过的一些测试更新了这个问题。不应该在使用优化时创建一个函数吗?我想知道是否需要以某种特殊方式创建对象才能利用该优化。 – dgaviola

+0

似乎没有办法优化。尽管v8创建隐藏类,但构造函数中的函数是实例变量。我能想到的唯一解决方法是使用原型,并像'self'一样定义'var pro = Person.prototype;'。然后代替'self.fullName = function()'使用'pro.fullName = function()'。至少代码将看起来一样:)对于这个问题,可以应用http://think-robot.com/2009/06/hitch-object-oriented-event-handlers-with-jquery/ for jQuery 。 –

+0

使用'自我'的好处是你可以在任何知道它会指向对象的地方使用。我正在使用一些类似于您所说的解决方法,但您需要记住这样做。但是,是的,可能目前还没有其他选择,以提高效率。 – dgaviola