JavaScript学习笔记:继承

192 阅读3分钟

类的多态:

重载和重写

  • 重载
    • java中的重载:函数名相同,但参数类型,数量不同或返回值不一样,这相当于把一个函数重载了(参数不同,一个方法当多个使用)
    • js中没有类似java这种的重载机制。js中是根据传参不同,实现不同的业务逻辑(严格说js没有重载)
  • 重写:子类重写父类上的方法

继承

子类继承父类中的属性和方法

js中的继承机制和其他后台语言是不一样的,有自己独特的处理方式

  • 1.原型继承

让B子类继承A父类

实现方案:子类的原型指向父类的一个实例

特点:

  • 不会把父类中的方法克隆一份给子类,而是建立了子类和父类之间的原型链查找机制
  • 重定向子类的原型后,默认丢失了原本的constructor属性(或者原本在原型上的设置的属性和方法)
  • 子类或子类的实例,可以基于原型链“肆意”修改父类上的属性方法,对父类造成一些“不必要的破坏”
  • 会把父类中私有属性方法作为子类公有的属性方法继承过来(父类中不管是公有还是私有,最后都变为子类公有的,这样不好)
function A(){
    this.x=100
}
A.prototype.getX=function getX(){
    console.log(this.x)
}

function B(){
    this.y = 200
}
// 让B的原型指向new A的实例,这样new B的实例既可以访问B的,也可访问A的
B.prototype = new A
B.prototype.getY=function getY(){
    console.log(this.y)
}
let b = new B

2. call继承

把父类当做普通函数执行,让其执行时方法中this变为子类的实例即可

特点:

  • 只能继承父类中的私有属性(继承的私有属性赋值给子类实例的私有属性),而且是类似拷贝过来一份,而不是链式查找。
  • 因为只是把父类当做普通方法执行,所以父类原型上的公有属性方法无法被继承过来
function A(){
    this.x=100
}
A.prototype.getX=function getX(){
    console.log(this.x)
}

function B(){
// call继承
    A.call(this) // 此时this.x=100 相当于 b.x=100
    this.y = 200
}
B.prototype.getY=function getY(){
    console.log(this.y)
}
let b = new B

3. 寄生组合继承:call继承 + 变异版的原型继承共同完成

call继承实现:私有到私有

原型继承实现:公有到公有

function A(){
    this.x=100
}
A.prototype.getX=function getX(){
    console.log(this.x)
}

function B(){
    A.call(this)
    this.y = 200
}
B.prototype = Object.create(A.prototype)
B.prototype.constructor = B // 设置B的constructor
B.prototype.getY=function getY(){
    console.log(this.y)
}
let b = new B

Object.create(obj): 创建一个空对象,让其__proto__指向obj(把obj作为空对象的原型)

4. ES6创建类用class

  • extends 继承和寄生组合继承基本类似
  • 一旦使用extents实现继承,只要自己写了constructor,就必须写super,否则报错
  • super 类似 A.call(this)
class A{
    constructor(){
        this.x = 100
    }
    // 设置私有属性,这样和在构造函数中的this.xxx = xxx 没区别(ES7)
    num = 100 
    // 设置到A.prototype上的方法
    getX(){
        console.log(this.x)
    }
    
    // 把A当做普通函数对象设置的属性和方法
    static n = 200
    static getN(){}
}
// extends 继承和寄生组合继承基本类似
class B extends A {
    constructor(){
        //一旦使用extents实现继承,只要自己写了constructor,就必须写super,否则报错
        // super 类似 A.call(this)
        super() 
        this.y = 100
    }
     getY(){
        console.log(this.y)
    }
}
console.log(new A) // {x:100,num:100}

真实项目中使用继承的地方

  • react 中创建类组件

    class Vote extends React.Component{}
    
  • 自己写插件或类库的时候

    例如自己封装一个组件,需要用到公共的属性方法时,可以继承过来使用