js的原型链与继承--红宝书笔记

154 阅读2分钟

什么是原型链?

几个概念,构造函数、原型、实例

  1. 每个构造函数都有一个prototype指向原型对象
  2. 原型对象的constructor指向构造函数
  3. 每个实例都包含一个指针_proto__指向其原型,有个constructor指向其构造函数
  4. 访问属性或方法会由原型链,一层层向上查找到顶层 Object.prototype
  5. Object的原型指向null

继承

原型链继承
function SuperType(){
    this.property = true
}

SubType.prototype = new SuperType()
// 修复原型链继承 constructor指向问题
Object.definePrototype(SubType.prototype,'constructor',{
    enumerable:false,
    value:SubType,
    writable:true
})

缺点:

  • 原型中包含的引用值会在所有实例中共享,属性要在构造函数定义,不在原型上,以防共享。
  • 子类型在实例化时不能给父类型的构造函数传参。
盗用构造函数
function SuperType(name){
    this.name = name
}
function Subtype(){
    SuperType.call(this'zhangsan') // 可传参
}

缺点:

  • 必须在构造函数中定义方法,子类不能访问父类原型上定义的方法
组合继承(原型链+构造函数)
function SuperType(name){
    this.name = name;
    this.color = ['red','blue']
}
SuperType.prototype.sayNamr = function(){
    console.log(this.name)
}
function Subtype(name,age){
    SuperType.call(this,name) // 可传参
    this.age = age
}
SubType.prototype = new SuperType();

tip:综合原型链及构造函数,使用最多

原型式继承
function object(o){
    function F(){}
    F.protoitype = o;
    return new F()
}
<!--es5后-->
使用Object.create(person,{
    name:{
        value:'greg'
    }
})
  • 不需要单独创建构造函数,由实例直接构建,属性中包含的引用值始终共享。
寄生式继承
function createAnother(o){
    let clone = object(o);//调用函数创建新对象
    clone.sayhi = function(){//增强对象
        console.log('hi')
    }
    return clone
}
  • 在原型式基础上加上新方法,类似构造函数,新方法难以重用
寄生式组合继承
function inheritPrototype(subType,superType){
    let prototype = object(superType.prototype);//调用函数创建新对象
    prototype.constructor - subType;//增强对象
    subType.prototype = prototype
}
function SuperType(name){
    this.name = name;
    this.color = ['red','blue']
}
SuperType.prototype.sayNamr = function(){
    console.log(this.name)
}
function Subtype(name,age){
    SuperType.call(this,name) // 可传参
    this.age = age
}
inheritPrototype(SubType,SuperType)

类(es6)

class Foo{
    //构造函数
    constructor(){}
    //访问和设置访问器
    get name(){
        return this.name_
    }
    set name(newName){
        this.name_ = newName
    }
    静态类方法
    static indentify(){}
}
class Bus extends Foo{
    //super 可在构造函数,实例方法,静态方法内部使用
    constructor(){
        //调用父类构造函数,不要在super之前使用this
        super()
    }
    static identify(){
        super.identify()
    }
}


//类混入实现我多类继承
class Vehicle{}
let FooMixin = (Superclass)=>class extends Superclass{
    foo(){
        console.log('foo')
    }
}
let BarMixin = (Superclass)=>class extends Superclass{
    bar(){
        console.log('foo')
    }
}
function mix(BaseClass,...Mixins){
    return Mixins.reduce((accumulator,current)=>current(accumulator),BaseClass)
}
class Bus extends Mix(Vehicle,FooMixin,BarMixin)