一张图搞懂原型、原型对象、原型链

基本概念

在javascript中,函数可以有属性。 每个函数都有一个特殊的属性叫作原型(prototype)
每个对象拥有一个原型对象 [[Prototype]] / __proto__ / Object.getPrototypeOf(object1)
通过原型对象一级一级的往上找的这个过程就是原型链

原型

每个函数都有一个特殊的属性叫作原型(prototype), 默认为空函数,可以重写

function fn1() {}
console.log(fn1.prototype)
image.png

重写原型之后会导致 constructor 指向错误

fn1.prototype = {}
console.log(fn1.prototype)
image.png

需将 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

Function、Array 的原型的原型对象都指向 Object 的原型

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
}

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('我的职责是:好好学习,天天向上!')
}

const s1 = new Status('Tom', 20, '男', '20041002')
s1.duties()
// s1.myself() 

 通过对象冒充(call/apply)的方式继承时,只能继承构造函数里面的属性及方法,不能继承原型上面的

对象冒充(call/apply) + 实例化构造函数的模式实现继承

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 = 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

原型链关系图

原型链关系图

【笔记不易,如对您有帮助,请点赞,谢谢】

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容