原型和原型链 - pod4g/tool GitHub Wiki

关于原型和原型链的一点儿感想

每一个对象都有__protp__属性,每一个函数都有prototype属性,对象的__proto__和这个对象的构造函数的prototype指向的是同一个对象,这个对象我们称之为原型对象


function Person(name, age) {
  this.name = name
  this.age = age
  this.say = function () {
    console.log('name:', this.name)
    console.log('age:', this.age)
  }
}

let person = new Person('云崇', 29)

person.__proto__ === Person.prototype

为什么有了prototype,还要有__proto__ 呢?

这就是程序设计的冗余性,因为如果只有prototype的话,一个对象,就不能方便地访问自己的原型对象,只能使用这个对象的构造器.prototype

的形式进行访问,很不方便

由于原型对象也是对象,故其也有__proto__,所以这就形成了一条链,我们称之为原型链

原型对象含有一个constructor,会指回向构造器

两个与原型有关的api

Object.create

创建一个新对象,并把新对象的__proto__指向传入的参数

const p = { name: 'yunchong', age: 29 }
const p2 = Object.create(p)

console.log(p2.name) // yunchong
console.log(p2.age) // 29

p2.__proto__ === p

在这个api出来以前,我们是怎么干的呢?

const p = { name: 'yunchong', age: 29 }

function Person() {}

Person.prototype = p

const p2 = new Person()

console.log(p2.name) // yunchong
console.log(p2.age) // 29

p2.__proto__ === p

其实Object.create 就是上述代码的语法糖,直接又方便地创建以一个以某个对象作为原型的对象而不用写一大坨代码

我们也常常使用Object.create(null) 来创建超轻量级的对象,轻量是因为其没有原型

Object.getPrototypeOf

上面说过,__proto__可以访问到对象的原型对象,但是这个__proto__毕竟不是es规范规定的,以后如果删除掉(或者不在暴露出去),那么其实es也提供了一个api来拿到__proto__

const p = { name: 'yunchong', age: 29 }
const p2 = Object.create(p)

const prototypeObject = Object.getPrototypeOf(p2)

prototypeObject === p2.__proto__
prototypeObject === p
p2.__proto__ === p