Js继承大汇总
想要继承,那么必须有个父类,子类通过继承的方式可以拥有父类的属性和方法。通俗的来说就像是生活中的儿子继承父亲的财产,子承父业类似道理,以下是js的七种继承方式:
1.原型链继承
继承就是相当于复制,原型链继承就是将父类的实例对象赋值给子类的原型对象,让子类的原型对象指向父类的实例对象,从而达到继承的效果。
// 父类构造函数
function Parent() {
this.money = 100000
this.hobbys = ['eat', 'sleep'];
}
// 子类构造函数
function Child(ideal) {
this.ideal = ideal;
}
Child.prototype = new Parent(); // 原型继承核心
Child.prototype.makeMoney = function (){
console.log('理想是'+this.ideal)
}
const child1 = new Child("努力赚钱,实现财务自由")
child1.makeMoney();
child1.hobbys.push('play')
console.log(child1.hobbys); // ['eat', 'sleep', 'play', 'work']
const child2 = new Child("努力赚钱,去旅游看最美的风景")
child2.makeMoney();
child2.hobbys.push('work');
console.log(child2.hobbys); // ['eat', 'sleep', 'play', 'work']
缺点:多个子类实例对象会对父类引用类型的属性进行篡改
2. 借用构造函数式继承
借用构造函数就是指在子类的构造函数中调用父类的构造函数来实现继承
function Parent(money) {
this.money = money;
}
Parent.prototype.eat = function () {
console.log('吃饱饭才有力气干活')
}
// 子类构造函数
function Child(money, dream) {
Parent.call(this, money); // 组合继承的核心
this.dream = dream;
}
Child.prototype.say = function () {
console.log('我有'+this.money+'钱,我的梦想是'+this.dream);
}
const child = new Child('一百万', '财务自由');
child.say();
child.eat(); // 报错:Uncaught TypeError: child.eat is not a function
缺点:
1、只能继承父类实例的属性和方法,不能继承父类原型的属性和方法
2、无法实现复用,每个子类都有父类实例函数的副本,影响性能
3. 组合式继承
组合式继承就是原型链继承和借用构造函数继承的组合,通过原型链继承实现对父类的原型属性和方法的继承,通过借用构造函数实现对父类实例的继承
function Parent(money) {
this.money = money;
}
Parent.prototype.save = function () {
console.log('我的总资产是'+this.money);
}
// 子类构造函数
function Child(money, dream) {
Parent.call(this, money);
this.dream = dream;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child; // 修正construct的指向
Child.prototype.say = function () {
console.log('我的梦想是'+this.dream);
}
const child = new Child('一百万', '财务自由');
child.save();
child.say();
console.log(child); //下面图片就是输出
缺点:
1、调用了两次父类的构造函数
2、原型对象上有些重复的属性
4. 原型式继承
原型式继承就是将一个对象复制给空对象的原型,然后返回这个空对象的实例对象,相当于对传入的对象进行一次浅复制
function extend(obj) {
function F() {
}
F.prototype = obj;
return new F();
}
缺点:
1、和原型链继承一样,多个实例对象对引用类型的属性存在篡改的可能
2、无法传递参数
5. 寄生式继承
寄生式继承就是在原型式继承的基础上的增强,也就是增强对象的方法,然后返回那对象
function parasitic(obj) {
const instance = extend(obj);
instance.sayHello = function () {
console.log('hello');
}
return instance;
}
缺点:和原型式继承的缺点一样
6. 寄生组合式继承
寄生组合式继承是寄生式继承和借用构造函数继承的结合
function paraCom(superClass, subClass) {
const prototype = Object.create(superClass.prototype);
prototype.constructor = subClass;
subClass.prototype= prototype;
}
function Parent(money) {
this.money = money;
this.hobbys = ['eat', 'sleep'];
}
Parent.prototype.property = function () {
console.log('我的总资产是'+this.money);
}
function Child(money, skill) {
Parent.call(this, money);
this.skill = skill;
}
paraCom(Parent, Child);
Child.prototype.ability = function () {
console.log('我的技能是'+this.skill)
}
const child1 = new Child('一百万', '唱跳rap');
child1.hobbys.push('play'); // ["eat", "sleep", "play"]
console.log(child1);
child1.property();
child1.ability();
const child2 = new Child('一百万', '唱跳rap');
child2.hobbys.push('work'); // ["eat", "sleep", "work"]
console.log(child2);
child2.property();
child2.ability();
优点:
1、多个实例对象对引用类型属性不会进行篡改
2、只调用了一次父类的构造函数
3、原型上不会出现重复多余不必要的属性
此方法是最成熟的继承方法
7、ES6类的继承
es6通过class关键字来定义类,通过关键字extends来实现继承
class Parent{
// 通过constructor来定义构造函数
constructor(money) {
this.money = money;
this.hobbys = ['eat', 'sleep'];
}
// 方法
property() {
console.log('总资产是'+this.money);
}
}
class Child extends Parent {
constructor(money, skill) {
super(money); // 继承父类
this.skill = skill;
}
ability() {
console.log('我的技能是'+this.skill);
}
}
const child1 = new Child('两百万', '唱跳rap');
console.log(child1);
child1.hobbys.push('work');
child1.property();
child1.ability();
const child2 = new Child('两百万', '唱跳rap');
console.log(child2);
child2.hobbys.push('play');
child2.property();
child2.ability();