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()也是自己的实例