Skip to content

js继承有哪些方法

继承的方式

构造函数继承、原型链继承、组合继承、class继承

1、构造函数继承

使用 call 来改变父类 this 的指向,来调用父类的属性和方法。
缺点:只能继承父类实例上的属性和方法,不能继承父类原型上的属性和方法

js
const Parent = function (name){
    this.name = "parent name";
}
const Child = function (){
    Parent.call(this);
    this.age = 25;
}
const child1 = new Child();
console.log(child1.name) // parent name;
console.log(child1.age) // 25;

2、原型链继承

子类的原型指向父类的实例来继承父类的属性和方法

  • 优点:可以继承父类的实例方法和属性,也能继承父类原型上的属性和方法
  • 缺点:对于引用类型改变,多个实例会相互影响。 创建子类的实例时不能像父类的构造函数中传递参数
JS
const Parent = function (){
    this.name = ["我是父类的属性name,我是个数组,引用类型"];
     this.age = 50;
}
Parent.prototype.say = function (){
   console.log("我是父类property上的方法。");
}
const Child  = function(){
   this.role = "我是儿子";
}
Child.prototype = new Parent();
const child1 = new Child();
const child2 = new Child();
child1.name[0] = "我是child1我改变了名字";
child1.age = 22;
child2.age = 24;
console.log(child1.name); //我是child1我改变了名字
console.log(child1.age); //22
console.log(child2.name); //我是child1我改变了名字
console.log(child2.age); //24

3、组合继承(原型链和构造函数组合继承)

将原型链继承和构造函数组合到一起继承,通过原型链来继承父类原型上的属性和方法,通过构造函数继承父类实例的属性和方法。
缺点:使用子类创建实例的时候,原型中会存在两份相同的属性和方法。

js
let Parent = function (name) {
  this.name = ["父类"];
};
Parent.prototype.say = "父类原型上的属性";
let Child = function () {
  Parent.call(this);
  this.childName = "子类";
};
Child.prototype = new Parent();
let child1 = new Child();
child1.name[0] = 222;
console.dir(child1);
/***
 * 结果为
 {
    childName:"子类",
    name:[222],
    [[Property]]:{
        name:['父类'],
        say:'父类原型上的属性'
    }
 }
* */

4、class 继承

class 创建一个父类,然后通过 extends 继承父类,在子类的 constructor 调用 spuer()

js
class Parent {
  constructor() {
    this.name = "我是父类继承过来的属性";
  }
  say() {
    console.log("我是父类的方法");
  }
}
class Child extends Parent {
  constructor() {
    super();
    this.age = 24;
  }
}
let child1 = new Child();

ES5 和 ES6 继承的区别

  • ES5 继承:是先创建子类的实例,再将父类的属性绑定到子类的 this 上。
  • ES6 继承:是先创建父类的实例对象 this,再用子类的构造函数修改 this,因为子类没有自己的 this,所以必须调用父类的 super()方法,否则新建实例会报错。