【发布时间】:2021-05-07 18:00:46
【问题描述】:
我喜欢使用闭包创建具有私有属性的对象的一般风格。我不确定是在闭包内还是在对象的实际原型上创建原型方法是否更有效。考虑以下示例:
const A = function(a, b) {
this.a = a;
this.b = b;
};
A.prototype = {
add:function() { this.a += this.b; }
};
const B = (function() {
function add() { this.a += this.b; }
return function(a, b) {
return { a, b, add };
};
})();
示例 A 是一个带有原型的传统构造函数。使用它看起来像这样:
var a = new A(1, 1);
a.add(); // a.a == 2;
示例 B 是使用闭包的技术。使用它看起来像这样:
var b = B(1, 1);
b.add(); // b.a == 2;
我期望 a 的工作方式是 A 的每个实例都有 a 和 b 属性以及指向包含 add 方法的原型对象的指针。
我期望 b 工作的方式是 B 的每个实例都有 a 和 b 属性以及指向 add 方法的指针。 B 函数有一个包含 add 方法的闭包。 add 方法只在定义 B 时定义一次。这似乎是在 JS 中创建“原型”属性和方法的一种不错的方式。有谁知道这是创建具有“共享”属性的对象的高性能方法,还是使用原型的传统方法的可行替代方案?
【问题讨论】:
-
对不起,我完全误读了你的闭包示例!我猜还没有喝足够的茶... :-)
-
:-) 它绝对不会每次都重新创建
add,对此感到抱歉。 -
FWIW,我总是非常对孤立的合成微基准持怀疑态度。它们很少与您的代码实际执行的操作相匹配,这很重要,因为现代 JavaScript 引擎会根据代码的实际使用进行优化(分几个阶段)。此外,您必须经常做超过 1k 次的操作才能让现代 JS 引擎对其进行优化。 :-) 还要注意以较慢的使用速度为代价的更快的创建(因为您使用对象的频率通常比创建它们的频率高)。在this equally suspect benchmark 中,差异要小得多(尽管仍然很大)。
-
最后,我要提防过早的优化。我不知道这还为时过早,您很可能正在开发一个将定期分配数百万个对象的系统。但是,如果您根据
new速度慢(而不是出于个人风格原因)的规范执行此操作,我强烈建议您不要这样做。无论如何,玩得开心! :-) -
具体用例是在游戏中实例化对象,我可能不会有几百万个对象,但可能有几千个。在主游戏循环期间使用
new实例化对象时存在明显的延迟。这可以通过在循环开始之前进行对象池/实例化来克服,但是这一发现使我走上了这条微优化的道路,然后好奇心接管了。我主要关心的是使用这些对象。它们使用起来会更慢吗?他们肯定会占用更多的内存。我在创建适当的基准来测试这一点时遇到了麻烦。
标签: javascript constructor scope closures lexical-scope