How babel parses es6 extends inheritance

   ES6 Class can extendsimplement inheritance through keywords, which is much clearer and more convenient than ES5's implementation of inheritance by modifying the prototype chain, which is similar to inheritance in JAVA.

class Anima{
  constructor(name){
     this.name = name
  }
  say(){
    let a = 2
    console.log(`my name is ${this.name}`)
  }
}
class Cat extends Anima{
constructor(name,age){
     super(name);
     this.age =age;
  }
  eat(){
     console.log(`i like fish...`)
  }
}

  Let's first review the js inheritance implementation before es6. In "JavaScript Advanced Programming (Third Edition)" p162, there are 6 inheritance methods mentioned, and combined inheritance is relatively common.

//father
function  Father(name){
   this.name = name;
}
Father.prototype.say = function(){
   console.log('my name is '+this.name);
}

//Subclass
function Son(name,age){
  //Inherit parent class properties
  Father.call(this,name);
  this.age = age;
}
Son.prototype = new Father();
Son.prototype.hello = function(){
  console.log('hello,my name is '+this.name+','+this.age+'years old');
}

   Compared with the extends in ES6, it is obviously a lot more complicated, but because ES6 has not been widely popularized in China at present, and the compatibility of browsers is estimated, even if it is used, it will be converted to ES5 in combination with babel. So how does babel parse extends?

   http://babeljs.io/  Babel online conversion, here you can see how babel converts es6 to es5 in real time.

   For class, babel directly converts it into a function

 
  which has a _classCallCheck function to detect whether Anima is called as a normal function or a constructor (class).

function _classCallCheck(instance, Constructor) {
    if (! (instance instanceof Constructor)) {
        throw new TypeError('Cannot call a class as a function');
    }
}

  And for the methods in the class, after babel is converted, it is generated by the _createClass function,

var _createClass = (function() {
    function defineProperties(target, props) {
    	for (var i = 0; i < props.length; i++) {
    	    var descriptor = props [i];
            descriptor.enumerable = descriptor.enumerable || false;
            descriptor.configurable = true;
            if ("value" in descriptor) descriptor.writable = true;
            Object.defineProperty(target, descriptor.key, descriptor);
        }
    }
    return function(Constructor, protoProps, staticProps) {
    	if (protoProps) defineProperties(Constructor.prototype, protoProps);
    	if (staticProps) defineProperties(Constructor, staticProps);
    	return Constructor;
    };
})();

  There is a defineProperties function, which mainly defines the method of the object through Object.defineProperty, which also defines a series of parameters, which is actually the same as Anima.prototype.say = function(){...}.

_createClass(Anima, [{
    key: "say",
    value: function say() {
      var a = 2;
      console.log("my name is " + this.name);
    }
  }]);

   Object.defineProperty is also a new api of es5, which is also introduced in "JavaScript Advanced Programming (Third Edition)":

defineProperty receives 3 parameters Object.defineProperty(object name, property name, {descriptor}), in which the descriptor object property must be 4 property values,
wirtable: whether it is writable, when false, the object property value cannot be changed
configurable: whether it can be registered literally, when it is false, the property cannot be deleted, and the object property cannot be deleted through delete, even if the value of configurable is modified by calling Object.defineProperty() multiple times, it will be limited
. enumerable: can it be passed for-in traverse property
value: set property value

  Next is extends, which corresponds to the _inherits function

function _inherits(subClass, superClass) {
	if (typeof superClass !== "function" && superClass !== null) {
		throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
	}
	subClass.prototype = Object.create(superClass && superClass.prototype, {
		constructor: {
			value: subClass,
			enumerable: false,
			writable: true,
			configurable: true
		} });
	if (superClass) Object.setPrototypeOf ?
		Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

   The code is relatively simple, just a few lines, that is, to implement prototypal inheritance through Object.create, and let the constructor of the subclass re-point to itself, but this only inherits the prototype method of the parent class. In ES6, the super keyword will be used to call the parent class properties or methods of

var _this = _possibleConstructorReturn(this, (Cat.__proto__ || Object.getPrototypeOf(Cat)).call(this, name));

   The effect of this sentence is Anima.call(this,name). where Object.getPrototypeOf returns the prototype of the object, for example:

function Pasta(grain, width) {
    this.grain = grain;
    this.width = width;
}
// Create an object from the pasta constructor.
var spaghetti = new Pasta("wheat", 0.2);

// Obtain the prototype from the object.
var proto = Object.getPrototypeOf(spaghetti);
alert(proto == Pasta.prototype);//true

 Summarize:

   Babel parses ES6 extends into combined inheritance, but babel uses a lot of es5 api

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326526655&siteId=291194637