js继承的几种方式

110 阅读2分钟

原型链继承

父构造函数
function Father(name,age){
    this.name=name,
    this.age=age,
    this.arr=[1,2,3]
}
Fa.prototype.say= function (){
    console.log(this.age,this.name);
}
子构造函数
function Son(){  
}
Son.prototype = new Father('爸爸',88)  //把 Fa的构造函数挂到Son的原型链上
let son1 =new Son()
let son2 =new Son() 
console.log(son1.name);     //爸爸
console.log(son2.name);     //爸爸
console.log(son2.say());    //88 "爸爸"
son1.arr.push('4')
console.log(son1.arr);  //       [1, 2, 3, "4"]     
console.log(son2.arr);  //       [1, 2, 3, "4"]
// 因为数组是引用类型  son1 改了arr里边的值  那son2的arr也会跟着变

优点:书写简单

缺点:

  • 每个通过new Son()实例化的对象都会共享 Son构造函数的prototype,如果Son构造函数的prototype里边有一个变量是引用类型 那么一个实例化对象更改了他 另一个实例化对象的值也会改变
  • 无法在子构造函数里传值 感觉子构造函数像个僵尸

构造函数继承

function Father(name,age){
    this.name=name,
    this.age=age,
    this.arr=[1,2,3]
}
function Son(name,age){  
    Fa.call(this,name,age)    // 通过call 改变this指向 call会立即执行函数
    相当于把 父函数里边的内容写到这里来了  
}
let s1 =new Son('s1',18)
let s2 =new Son('s2',19)
s1.arr.push('4')
console.log(s1.name);   //s1
console.log(s2.name);   //s2    
console.log(s1.arr);  //[1, 2, 3, "4"]
console.log(s2.arr);  // [1, 2, 3]

优点:解决了原型链继承中构造函数引用类型共享的问题,同时可以向构造函数传参

缺点:无法继承父构造函数原型上的方法

组合继承

把原型和构造函数结合在一起 就是组合继承

function Father(name,age){
   this.name=name,
   this.age=age,
   this.arr=[1,2,3]
}
Father.prototype.say= function (){
   console.log(this.age,this.name);
}

function Son(name,age){  
   Father.call(this,name,age)    
}
Son.prototype=new Father('爸爸',88)   会覆盖Son原型
需要重新设置子类的constructo --> Son.prototype.constructor=Son

优点:解决了原型链和构造函数的继承问题
缺点: 父类构造函数被调用了两次 浪费内存

寄生组合继承

function Father(name,age){
    this.name=name,
    this.age=age,
    this.arr=[1,2,3]
}
Father.prototype.say= function (){
    console.log(this.age,this.name);
}

function Son(name,age){  
    Father.call(this,name,age)    
}
Son.prototype=Object.create(Father.prototype); 
Object.create()可以理解为复制了一份父类的原型对象
这样父构造函数更改了prototype也不会影响到子构造函数

优点: ↑↑↑↑

缺点: 好像也没啥

Es6 class继承

父类
class F{
    // 构造器
    constructor(name,number) {
        this.name = name;
        this.number = number;
    }
    sayHi() {
        console.log(`姓名 ${this.name}, 学号 ${this.number}`)
        // console.log('姓名 ' + this.name + ' , 学号' + this.number)
    }
}

子类通过extends继承父类
class S extends F{
    constructor(name,number,major) {
        super(name,number)   //必须要写super() 否则会报错 
        原理我也不懂嘿嘿 等我继续学习回来补  
        如果这里不写 constructor 就不用写super()
        this.major = major
    }
}
let s =new S('as',8,1)
console.log(s);   //S {name: "as", number: 8, major: 1}

看了别人的文章自己写的 很随便 自己理解也不是很深刻 如果有不对的地方请指正或者有啥要补充的