Javascript 类与函数返回对象
我注意到有两种不同的方法可以有效地用JavaScript编写类(或类)。以简单计数器类为例: 一个实类(用作Javascript 类与函数返回对象,javascript,performance,class,es6-class,Javascript,Performance,Class,Es6 Class,我注意到有两种不同的方法可以有效地用JavaScript编写类(或类)。以简单计数器类为例: 一个实类(用作新计数器1()) 返回对象的函数(用作计数器2()) 我有很多代码可以用这两种风格中的任何一种来编写。我应该用哪一种 这是我的理解: Counter1可以与instanceof和继承一起使用,但更详细,没有真正的私有属性(例如count属性是公开的) Counter2更简洁,具有真正的私有方法/状态(函数中只有局部变量),但不能与instanceof和继承一起使用。它还为每个实例创建inc
新计数器1()
)
返回对象的函数(用作计数器2()
)
我有很多代码可以用这两种风格中的任何一种来编写。我应该用哪一种
这是我的理解:
Counter1
可以与instanceof
和继承一起使用,但更详细,没有真正的私有属性(例如count
属性是公开的)
Counter2
更简洁,具有真正的私有方法/状态(函数中只有局部变量),但不能与instanceof
和继承一起使用。它还为每个实例创建inc
和get
函数的新副本,这可能会影响性能?我不知道。我推荐使用,因为
- 类方法是
类定义将“原型”中所有类成员方法的可枚举标志设置为false。这很好,因为如果我们对对象进行
,我们通常不需要它的类方法for..in
- 类有一个默认值
如果
构造函数中没有类
,则生成一个空函数,就像我们编写的一样构造函数
- 总是上课 类构造中的所有代码都将自动插入
- 类还可以包括getter/setter
- 我们还可以将方法分配给类函数,而不是它的“原型”
你可以更进一步。两者都不应该对性能有很大影响。虽然类(
Counter1
在您的示例中)在技术上有稍好的性能,但只有当您每秒创建数千个类实例时(这可能是一个糟糕的设计选择),这一点才明显
至于其他优点,两者都有优点和缺点。FunFunFunction是学习JavaScript的一个很好的YouTube频道,也是我第一次学习工厂函数(Counter
)的地方。频道所有者强烈支持使用class
es
其中一个原因是,您无法从this
关键字中获得与JS中实现类的方式一致的行为,因为它可能指的是调用函数的HTML元素,而不是您期望的对象
有关更多详细信息,请参阅
当然,这只是论点的一个方面,我确信也有使用类
的论点。我更喜欢工厂功能,但最终你真的只需要选择一个,并与它滚动
我应该用哪一种
这个问题基本上是个人喜好的问题。OOP的真正信徒当然会采用class
方法。一个明显的区别是,这将允许您子类化Counter1
,但不清楚您为什么要这样做,甚至OOP爱好者也警告不要构建过于复杂的类层次结构
是的,第二种选择确实在每个实例上放置有问题的方法,而不是原型。是的,这确实会在理论上造成一些性能损失。但这并不是你需要担心的事情,除非你正在编写一个游戏,每一百万个对象有一个计数器
您可能正在使用某种transpiler或在本机ES6环境中运行。如果出于某种原因,您不是,那么您的第二个备选方案当然有一个优势,即它将在过去十年中的任何浏览器中运行(如果您将方法重写为
inc:function(){count++;}
)。我将其放在一个jsperf页面中,以测试以任何一种方式创建新实例的速度:
以下是我的计算机上的结果(每秒创建新实例):
我不知道为什么带有类的Firefox的数量如此之高(希望它没有注意到代码没有任何效果,并且忽略了整个事情),或者为什么边缘数量如此之低
因此,至少在性能方面,真正的类要快得多,可能是因为它避免了为每个实例创建方法的新副本的开销
虽然冗长和缺少类的私有状态令人讨厌,但我认为性能优势更重要,但这取决于具体情况
编辑
我也对结果对象进行了测试调用inc()
和get()
,数字基本相同:
Test Chrome Firefox Edge
new Counter1(); 215,352,342 2,072,278,834 23,570,036
Counter2(); 14,309,836 35,564,201 9,801,748
尽管原型的属性仍然无法访问私有范围的变量,但带有函数构造函数的新关键字可能是最好的。(1)常规的旧对象文本可以包括getter和setter。(2) 在第二个示例中,“类方法”或“静态方法”可以很容易地直接放置在计数器2
上。(3) 现在还不清楚为什么有一个默认构造函数在这里是相关的。(4) 请提供文档说明“类总是使用strict
。我以为是ES6模块总是使用strict
。这个
关键字很棘手,特别是在混合方法和回调时,尽管有些静态类型系统(TypeScript,Flow)我接受这个答案,因为这是在两种情况都有可能的情况下,最有力的论据支持一种观点而不是另一种观点。
function Counter2(count = 0) {
return {
inc() {
count++;
},
get() {
return count;
},
};
}
Test Chrome Firefox Edge
new Counter1(); 217,901,688 2,086,800,399 31,106,382
Counter2(); 30,495,508 36,113,817 9,232,171
Test Chrome Firefox Edge
new Counter1(); 215,352,342 2,072,278,834 23,570,036
Counter2(); 14,309,836 35,564,201 9,801,748