js实现继承的几种方式

原型继承
function Person() {
  this.name = '小明'
  this.fruits = ['苹果']
  this.getName = function () {
    console.log(this.name)
  }
}
Person.prototype.get = function () {
  console.log('Person.prototype上的方法')
}
​
function Student() {}
Student.prototype = new Person()
​

优点:

  • 方法复用

  • 由于方法定义在父类的原型上,复用了父类构造函数原型上的方法。

const stu1 = new Student()
​
console.log(stu1.name);   //小明
console.log(stu1.fruits);   //['苹果]
stu1.getName()  //小明
stu1.get()  //Person.prototype上的方法

缺点:

  • 创建的子类实例不能传参。

  • 父类所有的引用类型数据 (对象,数组) 会被子类共享更改一个子类的数据,其他数据会受到影响,一起变化

const stu1 = new Student()
const stu2 = new Student()
stu1.name = '小花'
stu1.fruits.push("香蕉")
​
console.log(stu1.name);   //小花
console.log(stu1.fruits);   //['苹果','香蕉']
stu1.getName()  //小花
stu1.get()  //Person.prototype上的方法
​
console.log(stu2.name)  //小明
console.log(stu2.fruits)    //['苹果','香蕉']
stu2.getName()  //小明
stu2.get()  //Person.prototype上的方法
构造函数继承
function Person() {
  this.name = '小明'
  this.fruits = ['苹果']
  this.getName = function () {
    console.log(this.name)
  }
}
Person.prototype.get = function () {
  console.log('Person.prototype上的方法')
}
​
function Student() {
    Per.call(this)
}
​

优点

  • 父类的引用类型的数据 (对象,数组) 不会被子类共享,不会相互影响

const stu1 = new Student()
const stu2 = new Student()
stu1.name = '小花'
stu1.fruits.push("香蕉")
​
console.log(stu1.name);   //小花
console.log(stu1.fruits);   //['苹果','香蕉']
stu1.getName()  //小花
​
console.log(stu2.name)  //小明
console.log(stu2.fruits)    //['苹果']
stu2.getName()  //小明

缺点

  • 子类不能访问父类原型属性(Person.prototype)上的方法和参数

stu1.get()  //Error
stu2.get()  //Error
组合继承
function Person(name) {
  this.name = name
  this.fruits = ['苹果']
  this.getName = function () {
    console.log(this.name)
  }
}
Person.prototype.get = function () {
  console.log('Person.prototype上的方法')
}
​
function Student(name,age) {
  Person.call(this,name)
  this.age = age
}
Student.prototype = new Person()

优点

  • 子类实例创建可以传递参数。

  • 父类可以复用

  • 父类构造函数中引用类型的数据 (对象,数组) 不会被子类共享

const stu1 = new Student('李白',18)
const stu2 = new Student('杜甫',20)
stu1.name = '诗仙'
stu1.fruits.push("香蕉")
​
console.log(stu1.name,stu1.age);   //诗仙 18
console.log(stu1.fruits);   //['苹果','香蕉']
stu1.getName()  //诗仙
stu1.get()  //Person.prototype上的方法
​
console.log(stu2.name,stu2.age)  //杜甫 20
console.log(stu2.fruits)    //['苹果']
stu2.getName()  //杜甫 
stu2.get()  //Person.prototype上的方法

缺点

  • 会调用两次父类的构造函数,会有两份一样的属性和方法,影响性能,造成了不必要的消耗。

寄生组合继承(常用)
function Person(name) {
  this.name = name
  this.fruits = ['苹果']
  this.getName = function () {
    console.log(this.name)
  }
}
Person.prototype.get = function () {
  console.log('Person.prototype上的方法')
}
​
function Student(name,age) {
  Person.call(this,name)
  this.age = age
}
const Fn = function(){}
Fn.prototype = Person.prototype
​
Student.prototype = new Fn()

核心思想: 组合继承 + 原型继承结合两者的优点。 优点: 完美! 缺点:无!

const stu1 = new Student('李白',18)
const stu2 = new Student('杜甫',20)
stu1.name = '诗仙'
stu1.fruits.push("香蕉")
​
console.log(stu1.name,stu1.age);   //诗仙 18
console.log(stu1.fruits);   //['苹果','香蕉']
stu1.getName()  //诗仙
stu1.get()  //Person.prototype上的方法
​
console.log(stu2.name,stu2.age)  //杜甫 20
console.log(stu2.fruits)    //['苹果']
stu2.getName()  //杜甫 
stu2.get()  //Person.prototype上的方法
class类继承extends(常用)
class Person {
  constructor(name) {
    this.name = name
    this.fruits = ['苹果']
    this.getName = function () {
      console.log(this.name)
    }
  }
  get = function () {
    console.log('Person.prototype上的方法')
  }
}
class Student extends Person {
  constructor(name,age) {
    super(name) // 调用父类的constructor方法
    this.age = age
  }
}

js自己原生的继承方法
 

const stu1 = new Student('李白',18)
const stu2 = new Student('杜甫',20)
stu1.name = '诗仙'
stu1.fruits.push("香蕉")

console.log(stu1.name,stu1.age);   //诗仙 18
console.log(stu1.fruits);   //['苹果','香蕉']
stu1.getName()  //诗仙
stu1.get()  //Person.prototype上的方法

console.log(stu2.name,stu2.age)  //杜甫 20
console.log(stu2.fruits)    //['苹果']
stu2.getName()  //杜甫
stu2.get()  //Person.prototype上的方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值