(1)原型链继承
实例对象数据是共享的,容易造成修改的混乱,并且在创建子类型的时候不能向超类型传递参数
function Animal(){}
Animal.prototype.age = 3
Animal.prototype.sing = function(name){
console.log(`我是${this.name},我会唱歌`)
}
function Cat(name){
this.name = name
}
// 原型直接赋值实现继承
// Cat.prototype = new Animal() 等同于下面的
Cat.prototype = Animal.prototype
let c1 = new Cat('小橘')
c1.sing() // 我是小橘,我会唱歌
console.log(c1.age) // 3
// 此时我们再创建一个小狗,也继承 Animal 的原型
function Dog(name){
this.name = name
}
Dog.prototype = Animal.prototype
let c2 = new Dog('哈士奇')
console.log(c2.age) // 3
// 但当我们修改 cat 上的 age 时,dog 也会随之改变
Cat.prototype.age = 4
console.log(c1.age) // 4
console.log(c2.age) // 4
// 缺点:由此可见,实例对象所共享, 容易造成修改的混乱
(2)构造函数继承
此方法解决了不能向超类型传递参数的缺点,但方法都在构造函数中定义,无法实现复用,并且超类型原型定义的方法子类型也没有办法访问到
function Animal(name){
this.name = name
this.sing = function(name){
console.log(`我是${this.name},我会唱歌`)
}
}
// 子类调用超类型构造函数,通过 call 绑定this,传递参数
function Cat(name){
Animal.call(this,name)
}
let c3 = new Cat('大橘')
c3.sing() // 我是大橘,我会唱歌
(3)组合继承(原型 + 构造函数)
通过借用构造函数的方式来实现类型的属性的继承,通过将子类型的原型设置为超类型的实例来实现方法的继承
function Animal(name){
this.name = name
}
Animal.prototype.sing = function(name){
console.log(`我是${this.name},我会唱歌`)
}
// 子类调用超类型构造函数,通过 call 绑定this,传递参数
function Cat(name){
Animal.call(this,name)
}
// 利用原型继承超类型原型上的方法
Cat.prototype = Animal.prototype
let c4 = new Cat('狸猫')
c4.sing() // 我是狸猫,我会唱歌
(4)组合派生继承
function Animal(name) {
this.name = name;
}
Animal.prototype.eat = function () {
console.log("哇呜,吃..", this.name);
};
// 【重点3】修改原型的[类型描述]
Animal.prototype[Symbol.toStringTag] = Animal.name;
function Cat(name) {
Animal.call(this, name);
}
// 【重点1 派生】:解决公共原型被修改影响所有实例的问题
console.log('==========',Cat.prototype) // Object
Cat.prototype = Object.create(Animal.prototype);
console.log('==========',Cat.prototype) // Cat
// 【重点2】掰回歪曲的构造函数
console.log('----------',Cat.prototype.constructor) // Animal
Cat.prototype.constructor = Cat;
console.log('----------',Cat.prototype.constructor) // Cat
// 【重点3】修改原型的[类型描述]
Cat.prototype[Symbol.toStringTag] = Cat.name;
// 测试
var dogPrototype = Object.create(Animal.prototype);
console.log(Cat.prototype === dogPrototype); // false
var c5 = new Cat("布偶");
c5.eat();
(5)class 继承
class Duck{
constructor(legsNumber){
this.kind = "鸡"
this.legsNumber = legsNumber
}
// 此处的 run 也会被继承
run(){
console.log('跑的飞快!')
}
}
// extends 关键词
class Chicken extends Duck{
kind = "鸡"
constructor(name) {
super(2)
this.name = name
}
rap(){
console.log(`鸡你太美~ 我是${this.name},是只${this.kind},我有${this.legsNumber}条腿。`)
}
}
const c = new Chicken('坤坤')
c.rap()
c.run()
console.dir(c)