欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

babel是如何解析es6 extends继承的

程序员文章站 2022-04-16 12:43:31
...

   ES6 Class 可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多,这跟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...`)
  }
}

  我们先来回顾下es6之前的js继承实现,在《JavaScript 高级程序设计(第三版)》p162 中提到了有6种继承方式,组合继承算是比较常见了。

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

//子类
function Son(name,age){
  //继承父类属性
  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');
}

   相对于ES6中的extends明显繁琐很多,但是由于目前ES6在国内尚未大量普及,还有估计浏览器的兼容性,即使用到也会结合babel来转成ES5。那么babel是如何解析extends的呢?

   http://babeljs.io/ babel在线转换,在这里可以实时看到babel是如何将es6转为es5的。
babel是如何解析es6 extends继承的
            
    
    博客分类: javascript javscript继承es6babeles5

   对于class,babel直接将它转为一个function
babel是如何解析es6 extends继承的
            
    
    博客分类: javascript javscript继承es6babeles5
 
  其中有个_classCallCheck函数用来检测Anima是被当作普通函数调用还是构造函数(类)来调用。

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

  而对于类中的方法,babel转换后通过_createClass函数来生成,

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; 
    }; 
})();

  其中有个defineProperties函数,主要通过 Object.defineProperty来定义对象的方法,其中还定义了一系列的参数,这跟Anima.prototype.say = function(){...}作用其实是一样的。

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

   Object.defineProperty也是es5新的api,在《JavaScript 高级程序设计(第三版)》也有介绍:

defineProperty接收3个参数Object.defineProperty(对象名,属性名,{ 描述符 }),其中描述符对象属性必须是4个属性值,
wirtable : 是否可写,当为false时,对象属性值就无法改变
configurable : 字面意思 是否可注册,当它为false时,属性无法删除,及无法通过delete 删除对象属性,即使通过多次调 用Object.defineProperty()来修改configurable的值 也会受到限制
enumerable : 能否通过 for-in遍历属性
value : 设置属性值

  接下来就是extends,对应的是_inherits函数

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; 
}

   代码比较简单,寥寥几行,就是通过Object.create实现原型继承,让后让子类的constructor重新指向自己,但是这仅仅继承了父类的原型方法,ES6中会通过super关键字来调用父类的属性或者方法,

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

   这句话的作用就是Anima.call(this,name)。其中Object.getPrototypeOf返回对象的原型,例如:

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

 总结:

   babel将ES6的extends解析为组合继承,只不过babel使用了大量es5的api

  • babel是如何解析es6 extends继承的
            
    
    博客分类: javascript javscript继承es6babeles5
  • 大小: 37.9 KB
  • babel是如何解析es6 extends继承的
            
    
    博客分类: javascript javscript继承es6babeles5
  • 大小: 19.7 KB