ES6中的继承剖析
ES6中实现类的继承主要有这两个函数:
_createClass
1 //新建类 2 var _createClass = function () { 3 function defineProperties(target, props) { 4 for (var i = 0; i < props.length; i++) { 5 var descriptor = props[i]; 6 descriptor.enumerable = descriptor.enumerable || false; 7 //属性如果没有设置可枚举,则设置该属性为不可枚举,这里和es5不同,注意!
8 descriptor.configurable = true; 9 //设置该属性为可配置 10 if ("value" in descriptor) descriptor.writable = true; 11 //如果有值则设置为可改写 12 Object.defineProperty(target, descriptor.key, descriptor); 13 //使用es5的defineProperty函数来添加属性 14 } 15 } 16 17 return function (Constructor, protoProps, staticProps) { 18 //添加原型属性到原型上 19 if (protoProps) defineProperties(Constructor.prototype, protoProps); 20 //添加静态方法到类上 21 if (staticProps) defineProperties(Constructor, staticProps); 22 return Constructor; 23 }; 24 }();
_inherits
1 //核心函数,实现类的继承 2 function _inherits(subClass, superClass) { 3 //判断类型是否正确 4 if (typeof superClass !== "function" && superClass !== null) { 5 throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); 6 } 7 8 //设置子类的继承 9 //superClass && superClass.prototype : 如果superClass不为null,那么就使用superClass.prototype,否在使用superClass 10 //这个相当于es5的继承,想构建一个空对象,空对象中添加一个constructor属性指向子类构造函数,而这个空对象的__proto__指向 11 //父类的原型,然后再将子类的prototype指向这个空对象,代码表示: 12 //var obj = {constructor:subClass};obj.__proto__ = superClass.prototype;subClass.prototype = obj; 13 subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); 14 15 //添加父类的静态方法和属性 16 //(静态方法和属性就是直接定义在构造函数上的方法和属性,这些方法不需要将构造函数实例化就可以使用,比如: 17 // Human.run = function(){console.log('run');} (这是静态方法) 18 // Human.color = 'blue'; (这是静态属性) 19 // 这些方法和属性可以通过Human.run和Human.color直接引用) 20 // 21 //因为根据原型链的继承方法是没有将父类的静态方法和属性继承下来的 22 // es6就采用了设置构造函数的__proto__属性的方式来实现静态方法和属性的继承,因为es6不推荐直接设置__proto__, 23 //所以可以使用setPrototypeOf和getPrototypOf来设置和查看 24 // 这里需要注意一下: 25 //__proto__并不是只有构造函数的实例才拥有的,所有的对象都有这么个属性(至于这个属性的由来什么的就自己百度吧) 26 //为了了解为什么在构造函数上设置__proto__属性,你需要先知道继承静态方法和属性的效果; 27 //比如上面的Human的例子,有个run的静态方法和color的静态属性,如果你实现了继承,那么你的Man构造函数也可以直接使用 28 //run方法和color属性,即:Man.run()和Man.color。 29 //这么看就很好理解了,run和color在Human上,为了在Man上可以使用就需要设置__proto__指向Human,这样根据原型链Man就 30 //可以查找到父类的静态方法和属性 31 //同时这里设置了__proto__之后,可以使用Object.getPrototypeOf(subClass).call(this,....)来复制父类的属性 32 if (superClass) 33 Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; 34 35 }