写在前面
此系列来源于开源项目:前端 100 问:能搞懂 80%的请把简历给我
为了备战 2021 春招
每天一题,督促自己
从多方面多角度总结答案,丰富知识
ES5/ES6 的继承除了写法以外还有什么区别?
正文回答
// ES6
class Super {}
class Sub extends Super {}
const sub = new Sub();
Sub.__proto__ === Super;
子类可以直接通过 __proto__
寻址到父类。
// ES5
function Super() {}
function Sub() {}
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;
var sub = new Sub();
Sub.__proto__ === Function.prototype;
而通过 ES5 的方式,Sub.__proto__ === Function.prototype
ES5 和 ES6 子类 this
生成顺序不同。
ES5 的继承先生成了子类实例,再调用父类的构造函数修饰子类实例
ES6 的继承先生成父类实例,再调用子类的构造函数修饰父类实例。
这个差别使得 ES6 可以继承内置对象。
function MyES5Array() {
Array.call(this, arguments);
}
// it's useless
const arrayES5 = new MyES5Array(3); // arrayES5: MyES5Array {}
class MyES6Array extends Array {}
// it's ok
const arrayES6 = new MyES6Array(3); // arrayES6: MyES6Array(3) []
因为 this
生成顺序不同,所以需要在 constructor
中,需要使用 super()
扩展知识点
ES5 最常见的两种继承:原型链继承、构造函数继承
- 原型链继承
// 定义父类
function Parent(name) {
this.name = name;
}
Parent.prototype.getName = function () {
return this.name;
};
// 定义子类
function Children() {
this.age = 24;
}
// 通过Children的prototype属性和Parent进行关联继承
Children.prototype = new Parent("陈先生");
// Children.prototype.constructor === Parent.prototype.constructor = Parent
var test = new Children();
// test.constructor === Children.prototype.constructor === Parent
test.age; // 24
test.getName(); // 陈先生
我们可以发现,整个继承过程,都是通过原型链之间的指向进行委托关联,直到最后形成了”由构造函数所构造“的结局。
- 构造函数继承
// 定义父类
function Parent(value) {
this.language = ["javascript", "react", "node.js"];
this.value = value;
}
// 定义子类
function Children() {
Parent.apply(this, arguments);
}
const test = new Children(666);
test.language; // ['javascript', 'react', 'node.js']
test.value; // 666
构造继承关键在于,通过在子类的内部调用父类,即通过使用 apply()
或 call()
方法可以在将来新创建的对象上获取父类的成员和方法。
- ES6 的继承
// 定义父类
class Father {
constructor(name, age) {
this.name = name;
this.age = age;
}
show() {
console.log(`我叫:${this.name}, 今年${this.age}岁`);
}
}
// 通过extends关键字实现继承
class Son extends Father {}
let son = new Son("陈先生", 3000);
son.show(); // 我叫陈先生 今年3000岁
ES6 中新增了 class
关键字来定义类,通过保留的关键字 extends
实现了继承。实际上这些关键字只是一些语法糖
,底层实现还是通过【原型链之间的委托关联】关系实现继承。
区别于 ES5 的继承,ES6 的继承实现在于使用 super
关键字调用父类,反观 ES5 是通过 call
或者 apply
回调方法调用父类。