简体   繁体   中英

ES6 to ES5: Babel's implementation of class extension

Due to old browser support, we all use babeljs to transpile ES6 into ES5. When babel compiles a class which is extended from another class. A part of compiled code is something similar to this:

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

The top code block is used for extending static properties from the parent class. They have used Object.setPrototypeOf to change [[Prototype]] of child class. It is not to confuse that .prototype and [[Prototype]] is a completely separate thing.

What MDN says in its reference regarding the use of Object.setPrototypeOf is below:

Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine.

My question emerge here: if we can achieve the same result with another way why Babel uses Object.setPrototypeOf ? I have tried to copy all the static methods from the parent class (which I have previously assigned to that) by looping through the constructor Function object.

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

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

And it is also faster than babel's implementation! I have created something similar what babel does to extend a class and tested it in jsPerf . My top 5 test run result was very disappointing with Object.setPrototypeOf : 19% slower, 20 % slower and three times 21% slower.

I know there must have some reasons why Object.setPrototypeOf might need to use. I want to know. If it is about non-enumerable properties then we can definitely use some other methods.

If we can achieve the same result with another way why Babel uses Object.setPrototypeOf ?

Simply because there is no other way that achieves the same result. Just copying over the current values of all properties is not the same as dynamically inheriting from another object. Babel aims to be correct, not fast.

And it is also faster than babel's implementation! I have created something similar what babel does to extend a class and tested it in jsPerf.

Well, creating and extending classes is slow, and it does not matter. Using those classes - for example accessing the static properties - is the important aspect here. There's usually no problem is you mutate the [[prototype]] of a fresh (yet unused) object - the warning is more concerned about doing the mutation in the middle of the objects lifetime.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM