JavaScript原型链完整图解
1. constructor、prototype和__proto__基础关系
graph TD
A[构造函数Person] -->|prototype| B[原型对象Person.prototype]
B -->|constructor| A
C[实例对象person] -->|__proto__| B
style A fill:#f96,stroke:#333
style B fill:#9cf,stroke:#333
style C fill:#9f9,stroke:#333
2. 完整的原型链关系
graph TD
A[实例对象person] -->|__proto__| B[Person.prototype]
B -->|constructor| C[Person函数]
B -->|__proto__| D[Object.prototype]
D -->|__proto__| E[null]
C -->|__proto__| F[Function.prototype]
F -->|__proto__| D
G[Object函数] -->|__proto__| F
G -->|prototype| D
H[Function函数] -->|__proto__| F
H -->|prototype| F
H -->|constructor| H
style A fill:#f9f,stroke:#333
style B fill:#9cf,stroke:#333
style C fill:#f96,stroke:#333
style D fill:#ff9,stroke:#333
style E fill:#999,stroke:#333
style F fill:#f9f,stroke:#333
style G fill:#f96,stroke:#333
style H fill:#f96,stroke:#333
3. 重要概念说明
IMPORTANT
构造函数特点:
- 所有函数都是Function()的实例
- Function是自己的实例(特殊性)
- 函数的__proto__指向Function.prototype
原型对象特点:
- 所有原型对象都是Object()的实例
- 存放实例的公共属性和方法
- 原型对象的__proto__指向Object.prototype
原型链特点:
- 通过__proto__属性连接
- 查找终点是Object.prototype
- Object.prototype的__proto__是null
4. 属性查找流程
flowchart TD
A[访问对象属性] --> B{对象自身有该属性?}
B -->|是| C[返回属性值]
B -->|否| D{原型对象有该属性?}
D -->|是| E[返回原型对象的属性值]
D -->|否| F{是否到达Object.prototype?}
F -->|否| G[沿__proto__向上查找]
F -->|是| H[返回undefined]
G --> D
prototype 属性指向的对象就是原型对象;原型对象的constructor属性指向它的构造函数; 这个原型对象的prototype属性指向另一个原型对象,层层向上,直到Object.prototype,Object.prototype的prototype为null。
原型对象最主要的作用是用来存放实例对象的共有属性和方法。
显示原型就是利用 prototype 属性查找原型,只是这个是函数类型数据的属性。
隐式原型就是利用__proto__属性查找原型,这个属性指向当前对象的构造函数的原型对象,这个是所有类型数据都有的属性。
在 js 中,对象的构造函数就是Object(),所以对象的原型对象就是Object.prototype。又因为原型对象也是对象,那原型对象的原型对象就是Object.prototype(但Object.prototype的__proto__为null)。
根据图可以看出,整个查找过程就是沿着__proto__这条线向上查找,直到找到Object.prototype为止。这个结构就是原型链。所以原型链也叫做隐式原型链。 正因如此,在创建对象、数组、函数等等数据的时候,都自带一些属性和方法,这些属性和方法是在它们的原型上面保存着,所以它们自创建起就可以直接使用那些属性和方法。
在js中,函数也是一个对象,因此函数也有一个__proto__属性,这个属性指向Function.prototype。 在js中,所有函数都可以看做是Function()的实例,而Person()和Object()都是函数,所以它们的构造函数就是Function()。Function()本身也是函数,所以Function()也是自己的实例