我最近尝试为经常创建的值对象优化一些代码。 (三维向量,fwiw)
我尝试过的一件事是将构造函数从匿名方法工厂模式转换为普通的JavaScript构造函数。
这导致severe performance penalty让我感到惊讶,因为在我的last question中建议使用'new'和普通构造函数来讨论JavaScript构造函数/工厂模式。
很可能是我的测试过于简单,或者只是完全错误,或者是Chrome的JavaScript引擎或上述所有内容中最近的性能优化结果。无论如何,我真的很想知道为什么我的'优化'导致性能下降 - 而且 - 最重要的是:我的jsperf testrun有没有明显的问题?
答案 0 :(得分:4)
您的测试之间的主要区别是:
{}
is way faster than new Object
,这表明new
比使用{}
慢。 ([]
和new Array
也是如此。)
您的测试产生不同的结果:make
工厂函数的结果不是Make
对象。构造的Make
有一个原型,由所有Make
个对象共享。您的工厂函数的结果只是一个裸Object
,并且在其原型链(Object.prototype
)中有一个原型,而Make构造的对象有两个(Make.prototype
,后跟{ {1}})。
我创建了一个fork of your test,其工厂函数实际上使用非标准Object.prototype
属性返回Make
个对象(而不是简单的Object
),并且它比使用构造函数要慢得多。 IE不支持__proto__
,但Firefox和Chrome的搜索结果非常明确。
答案 1 :(得分:3)
构造函数优化的一个方面是共享属性,通常是方法。如果许多对象使用与方法相同的函数,或者共享其他命名属性,那么对原型的一个赋值将在从构造函数创建的所有对象中共享该属性的单个实例,从而减少内存开销,并且不需要重复为每个创建的对象分配每个这样的属性,减少构建时间开销。
由于您的样本不包含任何此类属性,因此您不会看到此类好处。但是,如果您的生产代码不包含构造对象的共享属性,则可能没有理由切换到构造函数。
所以,例如,如果你有代码like this:
function make(p) {
return {
parm: p,
addTwo: function() {return this.parm + 2;},
double: function() {return this.parm * 2;},
square: function() {return this.parm * this.parm;}
};
};
它的运行速度可能比这慢:
function Make(p) {
this.parm = p;
}
Make.prototype.addTwo = function() {return this.parm + 2;};
Make.prototype.double = function() {return this.parm * 2;}
Make.prototype.square = function() {return this.parm * this.parm;}
如果你创建了很多实例,它也会占用更多内存。