14

我最近尝试为经常创建的值对象优化一些代码。(一个三维向量,fwiw)

我尝试的一件事是将构造函数从匿名方法工厂模式转换为普通的 JavaScript 构造函数。

这导致了严重的性能损失,这让我感到惊讶,因为在我关于 JavaScript 构造函数/工厂模式的最后一个问题中非常推荐使用“新”和普通构造函数。

很可能是我的测试过于简单,或者完全是错误的,或者是最近在 chrome 的 JavaScript 引擎中进行的性能优化的结果,或者以上所有原因。无论如何,我真的很想知道为什么我的“优化”会导致性能下降——而且——最重要的是:我的 jsperf 测试运行有什么明显的问题吗?

4

2 回答 2

4

您的测试之间的主要区别是:

  • {}比使用快得多new Object,这表明它new比使用慢{}[](和也是如此new Array。)

  • Your tests produce different results: the result of your make factory function isn't a Make object. The constructed Make has a prototype, shared by all Make objects. Your result of your factory function is just a bare Object, and has a single prototype in its prototype chain (Object.prototype), whereas the Make constructed object has two (Make.prototype, followed by Object.prototype).

    I made a fork of your test, with a factory function that actually returns a Make object (instead a simple Object), using the non-standard __proto__ property, and it is much slower than a using a constructor. IE does not support __proto__, but the results from Firefox and Chrome look pretty definitive.

于 2013-01-02T20:31:03.413 回答
3

构造函数优化的一件事是共享属性,通常是方法。如果多个对象使用与方法相同的函数,或者共享其他命名属性,那么对原型的一个赋值将在从构造函数创建的所有对象之间共享该属性的单个实例,从而减少内存开销,并且不需要重复为创建的每个对象分配每个此类属性,从而减少构建时间开销。

由于您的样本不包含任何此类属性,因此您不会看到此类好处。但是,如果您的生产代码不包含构造对象的共享属性,则很可能没有理由切换到构造函数。

因此,例如,如果您有这样的代码:

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;}

如果您创建许多实例,它也会占用更多内存。

于 2013-01-02T20:29:04.187 回答