js继承

94 阅读2分钟

js继承的几种方式

1、原型链继承

优点:父类放方法可以复用
缺点:父类所有的应用数据类型(对象,数组)会被子类共享更改一个类的数据,其他数据会受到影响,一直变化。

function Person() {
  this.name = "小明"
  this.eats = ['苹果']
  this.getName = function () {
    console.log(this.name);
  }
}

//person原型的方法
Person.prototype.get = () => {
  console.log('Person.prototype上的方法');
}



function Student() { }
Student.prototype = new Person()

const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()

console.log('-----------------------------');

const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()

2、构造函数的继承

优点:父类的引用数据类型的数据不会被子类共享 不会相互影响。
缺点:子类不能访问父类数据的方法和参数

function Person() {
  this.name = "小明"
  this.eats = ['苹果']
  this.getName = function () {
    console.log(this.name);
  }
}

//person原型的方法
Person.prototype.get = () => {
  console.log('Person.prototype上的方法');
}


function Student(){
  Person.call(this)
}

const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
//stu1.get() 报错

console.log('-----------------------------');

const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
//stu2.get()  报错


3、组合式继承

优点: 1、父类可以复用 2、父类构造函数中的引用属性数据不会被子类共享 不会相互影响
缺点:会调用两次父类构造函数,会有两份一样的属性和方法 影响性能

function Person() {
  this.name = "小明"
  this.eats = ['苹果']
  this.getName = function () {
    console.log(this.name);
  }
}

//person原型的方法
Person.prototype.get = () => {
  console.log('Person.prototype上的方法');
}


function Student() {
  Person.call(this)
}
Student.prototype = new Person()


const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()

console.log('-----------------------------');

const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()

console.log(stu2);  //会输出两份 影响性能

4、寄生组合继承(推荐)

目前最优方案

function Person() {
  this.name = "小明"
  this.eats = ['苹果']
  this.getName = function () {
    console.log(this.name);
  }
}

//person原型的方法
Person.prototype.get = () => {
  console.log('Person.prototype上的方法');
}


function Student() {
  Person.call(this)
}


const Fn = function () { }
Fn.prototype = Person.prototype

Student.prototype = new Fn()


const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()

console.log('-----------------------------');

const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()


console.log(stu2);

5、ES6 class继承 推荐

目前最优方案


class Person {
  constructor() {
    this.name = '小明'
    this.eats = ['苹果']
    this.getName = function () {
      console.log(this.name);
    }
  }
  get = () => {
    console.log('Person.prototype上的方法');
  }
}



class Student extends Person { }

const stu1 = new Student()
stu1.name = '小花'
stu1.eats.push('香蕉')
console.log(stu1.name);
console.log(stu1.eats);
stu1.getName()
stu1.get()

console.log('-----------------------------');

const stu2 = new Student()
console.log(stu2.name);
console.log(stu2.eats);
stu2.getName()
stu2.get()

总结:

js的继承有5种方式:
原型链继承
构造函数继承
组合继承
以上三种相对都会有一定的确缺陷
更推荐以下两种
class继承
寄生组合继承