94-js-10-继承和原型

概述

继承的实现和js的原型

// 类
class Student {
    constructor(name, number) {
        this.name = name
        this.number = number
    }
    sayHi() {
        console.log(
            `姓名 ${this.name} ,学号 ${this.number}`
        )
    }
}

// 通过类 new 对象/实例
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.number)
xialuo.sayHi()

const madongmei = new Student('马冬梅', 101)
console.log(madongmei.name)
console.log(madongmei.number)
madongmei.sayHi()

用类实现继承

// 父类
class People {
    constructor(name) {
        this.name = name
    }
    eat() {
        console.log(`${this.name} eat something`)
    }
}

// 子类
class Student extends People {
    constructor(name, number) {
        super(name)
        this.number = number
    }
    sayHi() {
        console.log(`姓名 ${this.name} 学号 ${this.number}`)
    }
}

// 子类
class Teacher extends People {
    constructor(name, major) {
        super(name)
        this.major = major
    }
    teach() {
        console.log(`${this.name} 教授 ${this.major}`)
    }
}

// 实例
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.number)
xialuo.sayHi()
xialuo.eat()

// 实例
const wanglaoshi = new Teacher('王老师', '语文')
console.log(wanglaoshi.name)
console.log(wanglaoshi.major)
wanglaoshi.teach()
wanglaoshi.eat()

原型关系

// class实际上是函数,可见是语法糖
typeof People // 'function'
typeof Student // 'function'

// 隐式原型和显式原型
console.log(xialuo.__proto__)
/**
 * People
 *  constructor: class Student
 *  sayHi: ƒ sayHi()
 *  [[Prototype]]: Object
*/
console.log(Student.prototype)
/**
 * People
 *  constructor: class Student
 *  sayHi: ƒ sayHi()
 *  [[Prototype]]: Object
*/
console.log(xialuo.__proto__ === Student.prototype) // true

每个class都有显式原型 prototype
每个实例都有隐式原型 __proto__
实例的隐式原型 __proto__ 指向class的显式原型prototype

基于原型的执行规则

获取属性xialuo.name 或执行方法xialuo.sayhi()时

先在自身属性和方法找

如果找不到则去__proto__中找

执行原型上的方法

xialuo.__proto__.sayHi()
// 输出 undefined。 因为原型上没有相应的属性
xialuo.sayHi()
// 执行类似于 xialuo.__proto__.sayHi.call(xialuo)

原型链