SOURCE

/************************ 原型 ************************/

// 每个函数都有一个特殊的属性叫作原型(prototype), 默认为空函数,可以重写
function fn1() {}
console.log(fn1.prototype)

// 重写原型之后会导致 constructor 指向错误
fn1.prototype = {}
console.log(fn1.prototype)

// 需将 constructor 重新指向当前构造函数
fn1.prototype.constructor = fn1


/************************ 原型对象 ************************/

// 每一个函数的原型对象指向 Function 的原型
function fn() {}
console.log(fn.__proto__ === Function.prototype)    // true

// 每一个数组的原型对象指向 Array 的原型
const arr = []
console.log(arr.__proto__ === Array.prototype)    // true

// 每一个对象(除 new 出来的)的原型对象指向 Object 的原型
const obj = {}
console.log(obj.__proto__ === Object.prototype)    // true

console.log(Function.prototype.__proto__ === Object.prototype)    // true
console.log(Array.prototype.__proto__ === Object.prototype)    // true


/************************ 继承 ************************/

// 通过对象冒充(call/apply)的方式实现继承
function Person(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
    this.des = 'Person class'
}

Person.prototype.myself = function() {
    console.log('my name is' + this.name)
}

function Status(name, age, sex, student) {
    Person.call(this, name, age, sex)
    this.student = student
}

Status.prototype.duties = function() {
    console.log('我的职责是:好好学习,天天向上!')
}

function Teacher(name, age, sex, subject) {
    Person.call(this, name, age, sex)
    this.subject = subject
}

Teacher.prototype.duties = function() {
    console.log('我的职责是:认真上好每一堂课!')
}

const s1 = new Status('Tom', 20, '男', '20041002')
console.log(s1)
s1.duties()
// s1.myself() 
// 通过对象冒充(call/apply)的方式继承时,只能继承构造函数里面的属性及方法,不能继承原型上面的


// 对象冒充(call/apply) + 实例化构造函数的模式实现继承
function Person(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
    this.des = 'Person class'
}

Person.prototype.myself = function() {
    console.log('my name is' + this.name)
}

function Status(name, age, sex, student) {
    Person.call(this, name, age, sex)
    this.student = student
}

Status.prototype = new Person()
Status.prototype.constructor = Status
Status.prototype.duties = function() {
    console.log('我的职责是:好好学习,天天向上!')
}

const s2 = new Status('Tom', 20, '男', '20041002')
console.log(s2)
s2.duties()
s2.myself()
// 多实例化了一次构造函数

// 对象冒充(call/apply) + Object.create()
function Person(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
}

Person.prototype.myself = function() {
    console.log('my name is' + this.name)
}

function Status(name, age, sex, student) {
    Person.call(this, name, age, sex)
    this.student = student
}

Status.prototype = Object.create(Person.prototype)
Status.prototype.constructor = Status
Status.prototype.duties = function() {
    console.log('我的职责是:好好学习,天天向上!')
}

const s3 = new Status('Tom', 20, '男', '20041002')
console.log(s3)
s3.duties()
s3.myself()

// 在上面的方案里面少了一次构造函数的实例化


/************************ 原型链 ************************/

function Person(name, age, sex) {
    this.name = name
    this.age = age
    this.sex = sex
}

Person.prototype.des = 'Person class'
Person.prototype.myself = function() {
    console.log('my name is' + this.name)
}

function Status(name, age, sex, student) {
    Person.call(this, name, age, sex)
    this.student = student
}

Status.prototype = Object.create(Person.prototype)
Status.prototype.constructor = Status
Status.prototype.duties = function() {
    console.log('我的职责是:好好学习,天天向上!')
}

const s4 = new Status('Tom', 20, '男', '20041002')
console.log(s4.des)
console.log(s4.type)

// s4.des/s4.type 首先从 s4 实例上开始查找,找不到再从原型对象中找 
// Status.prototype 中也找不到接着再从原型对象中找
// Person.prototype 中找得到 des 返回结果,找不到 type 接着往原型对象中找
// null 到达原型链顶层,最后对找不到的属性返回 undefined


console 命令行工具 X clear

                    
>
console