内存视角看「类、原型、实例」

发布于:2025-09-10 ⋅ 阅读:(19) ⋅ 点赞:(0)

看山是山,看山不是山,看山又是山。

代码

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  speak() {
    console.log(`我叫${this.name},今年${this.age}`)
  }
}

const p1 = new Person("张三", 22)

内存分布(抽象图)

【栈内存】                           【堆内存】
───────────────────────────── ───────────────────────────────
变量名    → 引用地址               实际对象内容

Person ───────┐                 Function 对象(类构造函数){
              │                   prototype: { constructor: f, speak: f }}
         [0x001] ──────────────────────────────┐
                                               │
p1 ──────────┐                                 │
             │                                 ▼
             ▼                       { name: "张三", age: 22 }
         [0x002] --------------------→   __proto__ → Person.prototype

分析步骤

类 Person

  • 本质是一个 构造函数对象存在栈内存中,有引用指向堆内存的函数体)。
  • 在内存中会自动生成一个 Person.prototype 对象,里面存放方法(如 speak)。

Person.prototype

  • 存在于堆内存中。
  • 存放实例共享的方法(speak)和一个默认的 constructor 属性(指回 Person)。

实例 p1

  • 存在于堆内存中【实例的引用在栈,实例的实际数据在堆】,里面存放的是 独有的属性:{ name: “张三”, age: 22 }。
  • 它的 proto(隐藏属性,标准叫 [[Prototype]])指向 Person.prototype。

方法查找

  • 当执行 p1.speak() 时:
    • 先在 p1 自己身上查找 speak → 找不到
    • 顺着 proto 去 Person.prototype 找 → 找到并执行

栈和堆存什么?

  • 栈:存放基本类型值、引用地址、执行上下文等。
  • 堆:存放对象的实际内容(包括实例、原型对象、函数对象)。

代码打印验证

console.log(typeof Person) // "function" → 说明类本质是构造函数
console.log(Person.prototype) // { constructor: f, speak: f }
console.log(p1.__proto__ === Person.prototype) // true
console.log(p1.constructor === Person) // true

总结:

  • 类本质是函数(存在栈内存里),它有一个自动生成的 prototype 对象(存在堆内存里)。
  • 实例存在堆内存,存放独有属性;共享方法放在原型对象上。
  • 实例通过 proto 链接到类的 prototype,形成 原型链。

网站公告

今日签到

点亮在社区的每一天
去签到