土豆博客

JavaScript中的几种继承方式

# 一、原型链继承

思路:将父类的实例作为子类的原型

缺点:

1.原型对象的所有属性被所有实例共享。(一个实例修改了原型属性,另一个实例的原型属性也会被修改)

2.在创建 Child 的实例时,不能向 Person 传参

function Parent () {
  this.age = 50;
}

Parent.prototype.getAge = function () {
  return this.age;
}

function Child() {
  this.age = 25;
}

Child.prototype = new Parent();
Child.prototype.constructor  = Child
var c = new Child();
console.log(c.getAge())
# 二、借用构造函数继承

思路:直接利用call或者apply方法将父类构造函数的this绑定为子类构造函数的this

优点:

1.避免了引用类型的属性被所有实例共享

2.可以在Child中向Parent传参

缺点:

1.只能继承父类构造函数中的属性和方法,对于原型对象无法继承。

2.由于只能继承父类构造函数中的属性和方法,即方法都在构造函数中定义,无法实现函数复用

function Person(name){
	this.name = name;
}

Person.prototype.getName = function(){
	console.log(this.name);
}

function Child(name){
	Person.call(this,name);
}

var child=new Child('小炮');
console.log(child.name)
# 三、组合继承

即组合原型链继承和借用构造函数继承。

思路:使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承

特点:

1.可以继承父类原型上的属性,可以传参,可复用。

2.每个新实例引入的构造函数属性是私有的。

缺点:组合继承最大的问题就是无论什么情况下,都会调用两次父类构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部

function Person(name) {  
  this.name=name;
}
Person.prototype.getName=function (){
  console.log(this.name);
}
function Child(name,age) {  
  Person.call(this,name);
  this.age=age;
}
Child.prototype=new Person();
Child.prototype.constructor = Child;
var child = new Child('xiaopao',18);
child.getName(); 
console.log(child.age);
# 四、寄生组合式继承

即通过借用构造函数来继承属性,通过原型链的方式来继承方法,而不需要为子类指定原型而调用父类的构造函数,我们需要拿到的仅仅是父类原型的一个副本。因此可以通过传入子类和父类的构造函数作为参数,首先创建父类原型的一个复本,并为其添加constrcutor,最后赋给子类的原型。这样避免了调用两次父类的构造函数

function father(name) {
  this.faName = "father";
}
father.prototype.getFaName = function () {
  console.log(this.faName);
};
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}
function inheritPrototype(child, father) {
  var prototype = object(father.prototype);
  prototype.constructor = child;
  child.prototype = prototype;
}

function child(args) {
  this.chName = "child";
  father.apply(this, []);
}
inheritPrototype(child, father);
child.prototype.getcnName = function () {
  console.log(this.chName);
};
console.log(child.prototype.isPrototypeOf(new child())); //true
console.log(new child() instanceof child); //true
# 五、ES6中的继承

ES5的继承的实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面。ES6的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。可以通过extends关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

class A {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    getName() {
        return this.name;
    }
}

class B extends A {
    constructor(name, age) {
        super(name, age);
        this.job = "IT";
    }
    getJob() {
        return this.job;
    }
    getNameAndJob() {
        return super.getName() + this.job;
    }
}

var b = new B("Tom", 20);
console.log(b.name);
console.log(b.age);
console.log(b.getName());
console.log(b.getJob());
console.log(b.getNameAndJob());
code
top

扫码添加,一起进步

wechat-code

为了保障最佳预览体验,博客已不支持IE浏览器的访问,邀请您使用以下现代高级浏览器。

谷歌浏览器(推荐) 火狐浏览器

注:如果你使用的是360,QQ等双核浏览器,请开启极速模式