ES6到ES5:Babel实现的类扩展

时间:2018-01-20 19:49:26

标签: javascript ecmascript-6 babeljs ecmascript-5

由于旧的浏览器支持,我们都使用babeljs将ES6转换为ES5。当babel编译一个从另一个类扩展的类时。编译代码的一部分与此类似:

...
if (superClass)
    Object.setPrototypeOf
      ? Object.setPrototypeOf(subClass, superClass)
      : (subClass.__proto__ = superClass);
...

顶部代码块用于扩展父类的静态属性。他们使用Object.setPrototypeOf来更改子类的[[Prototype]]。不要混淆.prototype[[Prototype]]是完全独立的事情。

MDN在其关于使用Object.setPrototypeOf的参考文献中所说的内容如下:

  

根据现代JavaScript引擎优化属性访问的性质,改变对象的[[Prototype]],在每个浏览器和JavaScript引擎中都是非常慢的操作。

我的问题出现在这里:如果我们能用另一种方式达到相同的结果,为什么Babel会使用Object.setPrototypeOf?我试图通过循环构造函数对象来复制父类中的所有静态方法(我之前已经分配给它)。

...
var parentStaticProps = parentClass.prototype.constructor;

for (var prop in parentStaticProps) {
  childClass.prototype.constructor[prop] = parentStaticProps[prop];
}
...

它也比babel的实施更快!我创建了类似于babel扩展类并在jsPerf中测试它的东西。 我的前5名测试结果非常令人失望Object.setPrototypeOf:慢19%,慢20%,慢21%。

我知道必须有Object.setPrototypeOf可能需要使用的原因。我想知道。如果它是关于非可枚举的属性,那么我们肯定可以使用其他一些方法。

1 个答案:

答案 0 :(得分:5)

  

如果我们可以通过另一种方式获得相同的结果,为什么Babel会使用Object.setPrototypeOf

仅仅因为没有其他方法可以达到相同的效果。只是复制所有属性的当前值与从另一个对象动态继承不同。巴别塔的目标是正确,而不是快速。

  

它也比babel的实施更快!我创建了类似于babel扩展类并在jsPerf中测试它的东西。

好吧,创建和扩展类 很慢,并不重要。 使用这些类 - 例如访问静态属性 - 是这里的重要方面。通常没有问题是你改变了一个新的(未使用的)对象的[[prototype]] - 警告更关心的是在对象生命周期的中间进行变异。