对象的结构
对象中存储属性的区域实际有两个:
- 对象自身
- 比如直接通过对象所添加的属性,位于对象自身中。
- 在类中通过 x = y 的形式添加的属性,也位于对象自身中。
- 原型对象(Prototype)
原型
原型对象(Prototype)
- 对象中还有一些内容,会存储到其他的对象里(原型对象)。
- 在实例中会有一个属性用来存储原型对象,这个属性叫做___ proto___。
- 会添加到原型对象中的情况:
- 在类中通过 xxx( ){ } 方式添加的方法,位于原型中
- 主动向原型中添加属性或方法
- 访问原型对象的方法
实例.__proto__Object.getPrototypeOf(对象)
- 原型对象中的数据
- 实例中的数据(属性、方法等)
- constructor(对象的构造函数)
实例.__proto__.constructor
原型链
- 原型对象也有原型,这样就构成了一条原型链,根据对象的复杂程度不同,原型链的长度也不同。
实例.__proto__.__proto___- 实例的原型链:实例 --> 原型 --> 原型 --> null
- obj的原型链:obj对象 --> 原型 --> null
- 读取对象属性时,会优先查找自身的属性:
如果对象中有,则使用,没有则去对象的原型中寻找
如果原型中有,则使用,没有则去原型的原型中寻找
直到找到Object对象的原型(Object的原型没有原型(null))
如果找到原型链最后依然没有找到,则会返回undefined
原型链与作用域链区别
- 作用域链,是查找变量的链,找不到会报错。
- 原型链,是找属性的链,找不到会返回 undefined。
原型链的作用
所有的同类型对象他们的原型对象都是一个,也就意味着,同类型对象的原型链是一样的。
- 原型链的作用:相当于是一个公共的区域,可以被所有该类实例访问,可以将一个该类实例中,所有的公共属性(方法)统一存储到原型中,这样我们只需要创建一个属性,即可被所有实例访问。
const p1 = new Person()
const p2 = new Person()
p1 === p2 // false
p1.__proto__ === p2.__proto__ // p1、p2虽然不是同一个对象,但原型是相同的