ES5 和 ES6 的区别
ES5 的继承
实质是先创造子类的实例对象 this,然后再将父类的方法添加到 this 上面(Parent.apply(this))
ES6 的继承
先创建父类实例 this 通过 class、extends、super 关键字定义子类,并改变 this 指向, super 本身是指向父类的构造函数但做函数调用后返回的是子类的实例, 实际上做了父类.prototype.constructor.call(this), 做对象调用时指向父类.prototype,从而实现继承。
//ES5
function Super() {}
function Sub() {}
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;
var sub = new Sub();
Sub.prototype.constructor === Sub; // ② true
sub.constructor === Sub; // ④ true
sub.__proto__ === Sub.prototype; // ⑤ true
Sub.prototype.__proto__ == Super.prototype; // ⑦ true
// ES6
class Super {}
class Sub extends Super {}
var sub = new Sub();
Sub.prototype.constructor === Sub; // ② true
sub.constructor === Sub; // ④ true
sub.__proto__ === Sub.prototype; // ⑤ true
Sub.__proto__ === Super; // ⑥ true
Sub.prototype.__proto__ === Super.prototype; // ⑦ true
// 寄生组合式继承
// 通过借用构造函数来继承属性, 通过原型链来继承方法
// 不必为了指定子类型的原型而调用父类型的构造函数,我们只需要父类型的一个副本而已
// 本质上就是使用寄生式继承来继承超类型的原型, 然后再讲结果指定给子类型的原型
function c1(name) {
this.name = name;
this.color = ["red", "green"];
}
c1.prototype.sayName = function () {
console.log(this.name);
};
function c2(name, age) {
c1.call(this, name);
this.age = age;
}
// 第一步:创建父类型原型的一个副本
// 第二步:为创建的副本添加 constructor 属性, 从而弥补因重写原型而失去的默认的 constructor 属性
// 第三步:将新创建的对象(即副本)赋值给子类型的原型
function inheritPrototype(Child, Parent) {
// 继承原型上的属性
Child.prototype = Object.create(Parent.prototype);
// 修复 constructor
Child.prototype.constructor = Child;
}
inheritPrototype(c1, c2);
// c2的方法必须放在寄生继承之后
c2.prototype.sayAge = function () {
console.log(this.age);
};
区别于 ES5 的继承,ES6 的继承实现在于使用 super 关键字调用父类,反观 ES5 是通过 call 或者 apply 回调方法调用父类。
所以 ES6 和 ES5 的继承是一模一样的,只是多了 class 和 extends,ES6 的子类和父类,子类原型和父类原型,通过proto连接。
最后更新于
这有帮助吗?