为什么Babel修改子类的原型而不是复制静态属性?

14ifxucb  于 12个月前  发布在  Babel
关注(0)|答案(1)|浏览(128)

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

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

最上面的代码块用于从父类扩展静态属性。他们使用Object.setPrototypeOf来改变子类的[[Prototype]]。不要混淆.prototype[[Prototype]]是完全不同的东西。
MDN在其参考文献中关于Object.setPrototypeOf的使用的内容如下:
改变对象的Prototype,由于现代JavaScript引擎优化属性访问的方式,在每个浏览器和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可能需要使用。我想知道如果它是关于不可枚举的属性,那么我们肯定可以使用一些其他方法。

4urapxun

4urapxun1#

如果我们可以用另一种方法达到同样的结果,为什么Babel使用Object.setPrototypeOf
因为没有其他方法可以达到同样的效果。仅仅复制所有属性的当前值与从另一个对象动态继承不同。巴别塔的目标是正确,而不是快速。
而且它也比babel的实现要快!我创建了一些类似于babel扩展类的东西,并在jsPerf中测试了它。
好吧,创建和扩展类很慢,这并不重要。* 使用 * 这些类-例如访问静态属性-是这里的重要方面。通常你对一个新的(还没有使用过的)对象的prototype进行变异是没有问题的--警告更关心的是在对象生命周期的中间进行变异。

相关问题