类vs函数返回对象

时间:2017-10-15 02:36:01

标签: javascript performance class es6-class

我注意到有两种不同的方法可以在JavaScript中有效地编写类(或类类的东西)。以一个简单的计数器类为例:

真正的类(用作new Counter1()

class Counter1 {
  constructor(count = 0) {
    this.count = count;
  }
  inc() {
    this.count++;
  }
  get() {
    return this.count;
  }
}

返回对象的函数(用作Counter2()

function Counter2(count = 0) {
  return {
    inc() {
      count++;
    },
    get() {
      return count;
    },
  };
}

我有很多代码可以用这些样式中的任何一种编写。我应该使用哪种?

这是我的理解:

Counter1可以与instanceof和继承一起使用,但更详细并且没有真正的私有属性(例如,count属性被公开)。

Counter2更简洁,并且具有真正的私有方法/状态(只是函数中的局部变量),但不能与instanceof和继承一起使用。它还为每个实例创建incget函数的新副本,这可能会影响性能?我不知道。

4 个答案:

答案 0 :(得分:2)

我建议使用classes,因此,

  • 类方法是non-enumerable

    对于" prototype"中的所有类成员方法,类的定义将可枚举标志设置为false。这很好,因为如果我们for..in超过一个对象,我们通常不会想要它的类方法。

  • 类具有默认constructor() {}

    如果constructor构造函数中没有class,则会生成一个空函数,就像我们编写constructor() {}一样。

  • 课程始终为use strict

    类构造中的所有代码都自动在strict mode

  • 课程也可能包含getter / setter。
  • Static Methods

    我们也可以将方法分配给类函数,而不是它的"原型"。

您可以进一步here

答案 1 :(得分:0)

两者都不应该对性能产生很大影响。虽然类(在您的示例中为Counter1)在技术上具有稍好的性能,但只有在每秒创建数千个类的实例时才会注意到这一点(无论如何这可能是一个糟糕的设计选择)。

至于其他优点,两者都有优点和缺点。 FunFunFunction是一个了解JavaScript的绝佳YouTube频道,这是我第一次了解工厂功能(Counter)。频道所有者强烈赞成使用class es。

其中一个原因是你无法通过JS中实现类的方式从this关键字中获得一致的行为,因为它可能引用类似于HTML元素的函数被称为而不是你期望它的对象。

有关详细信息,请参阅this video

当然,这只是论证的一个方面,我确信也有使用class的论据。我更喜欢工厂功能,但最后你真的需要选择一个并滚动它。

答案 2 :(得分:0)

  

我应该使用哪个?

这个问题基本上是个人偏好的问题。 OOP的真正信徒当然会采用class方法。一个明显的区别是,这将允许你继承Counter1,但不清楚为什么你会想要这样做,甚至OOP爱好者警告不要建立过于复杂的类层次结构。

是的,第二种方法确实将问题的方法放在每个实例上,而不是原型上。是的,这确实会带来一些理论上的性能损失。但这不是你需要担心的事情,除非你用一个计数器为每一百万个物体写一个游戏。

据推测,您正在使用某种转换器或在本机ES6环境中运行。如果由于某种原因你不是,那么当然你的第二个替代方案的优点是它将在过去十年中在任何浏览器中运行(如果你将方法重写为inc: function() { count++; })。

答案 3 :(得分:0)

我把它放在jsperf页面中以测试新实例创建的速度:https://jsperf.com/class-vs-object-2

以下是我计算机上的结果(每秒创建的新实例):

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

我不知道为什么带有class的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