JavaScript原型属性被所有实例共享,不重复占用堆内存;函数的prototype对象独立存在于堆中,实例通过__proto__指向它,仅自身属性单独存储,实现“就近优先+共享后备”的内存优化机制。

原型属性本身不直接占用每个实例对象的堆内存,而是被所有实例共享——这是 JavaScript 原型机制在内存分配上的核心设计。
prototype 是函数专属的共享存储区
每个函数(包括 class 构造器)创建时,引擎会自动为其生成一个 prototype 对象,该对象存放在堆内存中。它不是为某个实例准备的,而是为“将来所有通过该函数 new 出来的对象”统一准备的共享区域。
- 这个 prototype 对象一旦创建,就独立存在,与任何实例无关
- 它的属性和方法(如
Person.prototype.say)只在堆中保存一份 - 多个实例(
p1、p2)都通过各自的__proto__指向同一个Person.prototype,不重复复制
实例对象自身不复制原型上的属性
当你执行 new Person(),新对象在堆中分配空间时,只存放自己独有的属性(比如 this.name = "Ada"),而不会把 Person.prototype.name 的值也拷贝一份进去。
- 如果实例上没有该属性,访问时会沿着
__proto__链向上查到 prototype - 若你在实例上赋值同名属性(如
p2.name = "Ada"),则会在该实例自身堆内存中新增一个属性,屏蔽原型上的同名属性 - 这种“就近优先 + 共享后备”的机制,节省了大量内存
内存中实际存在的四类关联结构
以 function Person() {} 为例,内存中存在四个逻辑层级:
立即学习“Java免费学习笔记(深入)”;
-
Person 函数本身:栈或堆中的一块函数对象空间,含
prototype属性(指向 prototype 对象) -
Person.prototype 对象:堆中独立对象,含
constructor、name、say等共享成员 -
实例对象(如 p1):堆中独立对象,含自有属性(如
age: 22),隐式原型__proto__指向Person.prototype -
原型链终点:
Person.prototype.__proto__ === Object.prototype,最终连到null
和字面量对象的内存表现不同
对比 const p = { name: "Alice" }:它没有 prototype,其 __proto__ 直接指向 Object.prototype;所有属性都属于自身,无法被其他对象共享。
- 字面量对象是“一次性快照”,每次创建都是全新堆分配
- 构造函数 + prototype 模式是“模板+实例”,适合需要多实例且行为一致的场景
- 从内存角度看,后者更省空间,尤其当方法较多、实例较多时优势明显


















