他们的区别
- 区别1: es5的类(其实就是函数) 可以普通函数调用
es6的类( class声明) 不可以普通函数调用
- 区别2: 通过es5实现的静态属性方法可以枚举
通过es6实现的静态属性方法不可枚举
- 区别3: es5 子类.__proto__ == Function.prototype
es6 子类.__proto__ == 父类
- 区别4: es5 实际先创建子类的实例对象`this`,在执行父类的构造函数添加实例
es6 先创建父类的实例对象`this`, (但是this.__proto__ = 子类.prototype) 然后再用子类的构造函数修改`this`
- 区别5: 父类不会进行变量提升
# es5 的继承实现
js 实现继承的方法有很多种原型链继承、构造函数继承、组合继承、寄生继承
但这些或多或少都有不足之处,所以笔者认为我们只需要记住一种就好了。寄生组合继承
首先,我们要明确我们要继承的东西:实例属性/方法 静态属性/方法 原型属性/方法
需要被继承的父类
function Sup(name) {
this.name = name; //实例属性
}
//静态
Sup.type = "静态属性type";
Sup.sleep = function () {
return "静态方法sleep";
};
//实例方法
Sup.prototype.say = function () {
console.log(`我是${this.name}`);
};
1。继承实例属性/方法
//子
function Sub(name, age) {
Sup.call(this, arguments);
this.age = age;
}
2.继承原型属性/方法
Sub.prototype = Object.create(Sup.prototype);
Sub.constructor = Sub;
3.继承静态属性/方法
for (let key of Object.keys(Sup)) {
// type sleep...
Sub[key] = Sup[key];
}
# es6 的继承实现
//上面的例子
// 父类
class Sup {
constructor(name) {
this.name = name;
}
say() {
console.log("我叫 " + this.name);
}
static sleep() {
console.log(`我在睡${this.type}觉`);
}
}
// static只能设置静态方法,不能设置静态属性,所以需要自行添加到Sup类上
Sup.type = "静态属性type";
// 另外,原型属性也不能在class里面设置,需要手动设置到prototype上,比如Sup.prototype.xxx = 'xxx'
// 子类,继承父类
class Sub extends Sup {
constructor(name, age) {
super(name);
this.age = age;
}
say() {
console.log("你好");
super.say();
console.log(`今年${this.age}岁`);
}
}
Sub.type = "子类自己的静态属性";
# 使用 babel 编译成 es5 的实现
# 编译后的父类
做了什么事?
- 一个立即执行函数,最后返回
Sup函数 _classCallCheck()检查是否是 this 是不是实例化的_createClass(类,实例方法,静态方法)给类|类的原型添加属性
var Sup = (function () {
function Sup(name) {
//区别1
_classCallCheck(this, Sup);
this.name = name;
}
//类 实例方法 静态方法
_createClass(
Sup,
[
{
key: "say",
value: function say() {
console.log("我叫 " + this.name);
},
},
],
[
{
key: "sleep",
value: function sleep() {
console.log("\u6211\u5728\u7761".concat(this.type, "\u89C9"));
},
},
]
);
return Sup;
})();
Sup.type = "静态属性type";
// instance是不是构造函数的实例
// 或者说 constructor的prototype.是否出现在instance的原型上
_classCallCheck(instance,Constructor){
if( !(instance instanceOf Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
_createClass(Constructor, protoProps, staticProps){
//实例方法
if(protoProps) {_defineProperties(Constructor.prototype,protoProps)}
//静态方法
if(staticProps) {_defineProperties(Constructor,staticProps)}
}
_defineProperties(Constructor,props){
for(let i =0 ;i<props.length;i++) {
let descriptor=props[i]
//enumerable,writable,
descriptor.enumerable = descriptor.enumerable || false;
//区别2
descriptor.configurable = true;
if ('value' in descriptor ) descriptor.writable = true;
Object.defineProperty(Constructor,props.key,descriptor)
}
}
# 编译后的子类
做了什么事?
- 也是运行立即执行函数,返回
Sub函数 _inherit()执行 原型继承- 创建
_super函数 - 创建
Sub函数(检查,调用_super,初始化自己的方法,返回this) 在这个this上做文章 _createClass类添加实例方法、静态方法
var Sub = (function (_Sup) {
_inherit(Sub, _Sup);
//放回一个方法
var _super =_createSuper(Sub)
function Sub(name, age) {
var _this;
// 检查是否当做普通函数调用,是的话抛错
_classCallCheck(this, Sub);
// 通过父类创建的实例对象,通过子类的构造函数修改this
_this = _super.call(this, name);
_this.age = age;
return _this;
}
_createClass(Sub, [
{
key: "say",
value: function say() {
console.log("你好");
_get(_getPrototypeOf(Sub.prototype), "say", this).call(this);
console.log("\u4ECA\u5E74".concat(this.age, "\u5C81"));
}
}
]);
return Sub;
})(Sup);
Sub.type = "子类自己的静态属性";
_inherits(subClass,supClass) {
if(typeof supClass !== 'function'&& supClass!==null)
{
throw new TypeError('超类必须是函数或是null')
}
//原型
subClass.prototype = (supClass && supClass.prototype,{
constructor:{
value:subClass,
enumerable:true,
configurable:true
}
})
//区别3 es6 给子类找到父类
if(superClass) _setPropertyOf(subClass,superClass)
}
_setPropertyOf(o,p) {
_setPropertyOf = Object.setPropertyOf || function setPropertyOf(o,p){
o.__proto__ = p
}
_setPropertyOf(o,p)
}
//接受一个子类构造函数 即立即执行里的function Sub ,在返回一个新函数
_createSuper(Sub){
//这个this是 就是子类实例Sub
return function _createSuperInternal(){
//检查 reflect.constructor 是否可用
var hasNativeReflectConstruct = _isNativeReflectConstruct();
let result;
//区分1 拿到 Sub.__proto__ == Sup
let Super=_getPrototypeOf(Sub)
if(hasNativeReflectConstruct) {
//区分2 sub实例的__proto == Super.prototype
let Target = _getPrototypeOf(this).constructor
// new Super() 第三个参数 作为新对象的构造函数 即是 result.__proto__ = Sub.prototype
result = Reflect.constructor (Super ,arguments ,Target )
//创建父实例,并且父实例的__proto__指向 Sub.
}
else {
result = Super.apply(this,arguments)
}
//返回 new的父类实例或者是一个方法
return _possibleConstructorReturn(this,result)
}
}
function _possibleConstructorReturn(self, call) {
if (call && (_typeof(call) === 'object' || typeof call === 'function')) {
return call
} else if (call !== void 0) {
throw new TypeError(
'Derived constructors may only return object or undefined'
)
}
return _assertThisInitialized(self)
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError(
"this hasn't been initialised - super() hasn't been called"
)
}
return self
}
必须调用super的原因
子没有this对象,需要通过父类创建
this 来源于 super调用(即 执行父构造创建实例,但是this指向的是Sub)