编辑代码

// 1,原型链
// 问题:父级中的各种属性会直接变为子级的原型属性,因此父级属性的改变会直接影响到所有的子级
// 注意:子级继承后,切记不可使用对象字面量来创建原型方法,因为会重写原型链
// 注意:子级中需要覆盖修改父级方法时,必须在替换原型语句的后面。
// 注意:instance.constructor 现在指向的是 SuperType。?
// 注意:原型链最顶层是 Object
function SuperType1() {
    this.name = "Tom"
    this.property = true
}

SuperType1.prototype.getSuperValue = function() {
    console.log(this.property)
}

function SubType1() {
    this.name = 'sub'
    this.subproperty = false
}

SubType1.prototype.getSubValue = function() {
    console.log(this.subproperty)
}

SubType1.prototype = new SuperType1()

let instance1 = new SubType1()

instance1.getSuperValue()

// 2,借用构造函数
// 问题:使用构造函数替换 this 的方式,不能继承原型链上的属性方法
// 问题:不能复用方法

// 构造函数
function SuperType(name, age) {
    this.name = name
    this.age = age
    // this.sayHi = function() {
    //     console.log(this.name)
    // }
}

SuperType.prototype.sayName = function() {
    console.log(this.name)
}

SuperType.prototype.job = 'worker'

function SubType(name, age) {
    SuperType.call(this, name, age)
    this.sayHi = function() { // 不能复用,意思就是如果要修改的话,实现不了
        console.log(this.name)
    }
}

SubType.prototype.sayAge = function() {
    console.log(this.age)
}

let instance = new SubType('Tom', 24)
let instance2 = new SubType('Noci', 30)
console.log(instance, instance2) // 不能获取到原型上的方法
instance.sayHi()
instance.sayAge()
instance2.sayHi()
instance2.sayAge()
// instance.sayName()

// 3,组合继承
// 使用 原型链继承 和 借用构造函数一起。原型链实现对原型属性和方法继承,借用构造函数实现对实例属性的继承

function SuperType3 () {
    this.name = name
    this.colors = ['red', 'yellow']
}

SuperType3.prototype.sayName = function() {
    console.log(this.name)
}

function SubType3(name, age) {
    // 继承属性
    SuperType3.call(this, name)
    this.age = age
}

// 继承方法
SubType3.prototype = new SuperType3()
SubType3.prototype.constructor = SubType3


// 4,原型式继承

let person4 = {
    name: 'Tom',
    friend: ['Nico', 'Leo']
}

let one = Object.create(person4)
one.friend.push('Coco')

let two = Object.create(person4)
two.friend.push('Ana') // 使用的是同一个原型,又是引用类型

console.log(two.friend)

// 5,寄生式继承
// 创建一个仅用于封装继承过程的函数,该函数在内部以某种方式增强对象
// 任何能够返回新对象的函数都适用于此模式

function createAnother(ori) {
    var clone = Object(ori)
    clone.sayHi = function() {
        console.log('hi')
    }
    return clone
}


// 6,寄生组合式继承
// 组合继承最大的问题:会调用两次超类型构造函数
// 思想:通过借用构造函数来继承属性,通过原型链的混成方式继承方法
// 优点:只调用了一次 SuperType6 的构造函数,避免了在 SubType6.prototype 上多余的属性

function inheritPrototype(subType, superType){ 
    var prototype = Object(superType.prototype); //创建对象
    prototype.constructor = subType; //增强对象
    subType.prototype = prototype; //指定对象
}

function SuperType6(name){ 
    this.name = name; 
    this.colors = ["red", "blue", "green"]; 
}
SuperType6.prototype.sayName = function(){ 
    alert(this.name); 
}; 
function SubType6(name, age){ 
    SuperType6.call(this, name); 
 
    this.age = age; 
} 
inheritPrototype(SubType6, SuperType6); 
SubType6.prototype.sayAge = function(){ 
    alert(this.age); 
};