Skip to content

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

  1. 构造函数特点

    • 所有函数都是Function()的实例
    • Function是自己的实例(特殊性)
    • 函数的__proto__指向Function.prototype
  2. 原型对象特点

    • 所有原型对象都是Object()的实例
    • 存放实例的公共属性和方法
    • 原型对象的__proto__指向Object.prototype
  3. 原型链特点

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