视频地址:【千锋前端JavaScript全套教程_JS零基础完美入门到项目实战】 https://www.bilibili.com/video/BV1W54y1J7Ed/?share_source=copy_web&vd_source=b1cb921b73fe3808550eaf2224d1c155
目录
12 原型和原型链
与面向对象相关的东西。
- 原型
- 解决问题:当需要给实例对象添加方法,直接书写在构造函数体内,这种行为不好。
12.1 构造函数的缺点
缺点:每次创建实例的时候,都会创建一个函数数据类型
多个函数方法,一模一样,但是占据了多份存储空间。
12.2 解决问题 __proto__
- 原型:每个构造函数天生自带一个属性prototype属性,是一个对象数据类型。
- 每个对象天生自带一个属性__proto__,指向所属构造函数的prototype
- 即对象的__proto__ === 构造函数的prototype,如下所示
function Person() {
}
Person.prototype.a = 100
// p1所属的构造函数就是Person
var p1 = new Person()
// p1.__proto__ === Person.prototype
- 当访问对象的成员的时候,首先在自己身上查找,如果没有,自动去对象的__proto__查找
- 下面的例子当访问p1.a的时候,p1没有a,自动去__proto__查找,又因为p1.__proto__===Person.prototype,所以就去Person的prototype查找:
function Person() {
}
Person.prototype.a = 100
// p1所属的构造函数就是Person
var p1 = new Person()
// p1.__proto__ === Person.prototype
console.log(p1.a)
原型上添加的东西在实例上可以访问。
- 如何解决问题
- 我们把需要添加给实例的方法,放在构造函数的原型(prototype)上
- 接下来就可以由 实例 进行访问使用
12.3 原型链
提出问题
问题1:实例对象身上的 __proto__ 指向谁?
问题2:Person.prototype 的 __proto__ 指向谁?
问题3:Person 的 __proto__ 指向谁?
12.3.1 问题1
-
问题1:实例对象身上的 __proto__ 指向谁
p1所属的构造函数是Person,所以p1的 __proto__ 指向Person的prototype
12.3.2 问题2
- 问题2 Person.prototype 的 __proto__ 指向谁?
Person.prototype的构造函数是谁
因为Person.prototype是一个对象数据类型(object)
在JS内所有Object数据类型都属于Object这个内置构造函数。
因此Person.prototype 的 __proto__ === Object.prototype
由此引出问题4和5
- 问题4:Object的prototype的 __proto__ 又指向谁
- 问题5:Object的 __proto__ 又指向谁
12.3.3 问题3
- 问题3:Person 的 __proto__ 指向谁?
Person是一个函数,函数本身是一个对象,就会有 __proto__
在JS内,所有的函数都属于内置构造函数Function 的实例,
因此,Person的 __proto__ 指向 Function的prototype
由此出现了问题6和问题7
问题6:Function.prototype的 __proto__ 指向谁?
问题7:Function 的 __proto__ 指向谁?
12.3.4 问题4
问题4:Object的prototype的 __proto__ 又指向谁
如果按照前面说的,Object的prototype是对象数据类型,其构造函数是Object,因此其__proto__就是Object的prototype。这样仿佛陷入死循环了。
注意:Object.prototype 在JS 内叫做顶级原型,不再有 __proto__了。
因此:Object.prototype.__proto__ = null
12.3.5 问题5
问题5:Object的 __proto__ 又指向谁
Object是一个内置构造函数,同时也是一个函数,同时也是一个对象
在JS内,所有的函数都属于内置构造函数 Function 的实例。(只要是函数,都是Function的实例)
Object 也是Function的实例
因此 Object.__proto__ === Function.prototype
12.3.6 问题6
问题6:Function.prototype的 __proto__ 指向谁?
Function.prototype是一个对象数据类型
只要是对象数据类型,那么就是Object的实例
Function.prototype的 __proto__ === Object.prototype
12.3.7 问题7
问题7:Function 的 __proto__ 指向谁?
Function也是一个内置构造函数,也是一个函数。
在JS内,所有的函数都属于内置构造函数 Function 的实例
Function 是 Function 的构造函数,
Function 是 Function 的实例对象,
Function 所属的构造函数是Function
因此:Function.__proto === Function.prototype
总结如下
12.3.8 原型链的概念
原型链
- 用 __proto__ 串联起来的对象链状结构
- 注意:使用 __proto__ 串联
- 每一个对象数据类型,都有一个属于自己的原型链。
- 原型链作用:访问对象成员
例子:
1、从实例化对象出发,黑色的是一条原型链
2、从Person构造函数出发,也串联起一条对象链状结构。
对象访问机制
- 当需要访问对象的成员的时候
- 首先在自己身上查找,如果有直接使用
- 如果没有,会自动去 __proto__ 上查找
- 如果还没有,就再去 __proto__ 上查找
- 直到Object.prototype都没有,就返回undefined