原型链不影响垃圾回收,GC仅依据对象可达性判定;原型对象按普通对象参与回收,其实例回收与原型无关,原型链不构成回收屏障,内存泄漏常源于隐含强引用而非原型链本身。

原型链本身不决定垃圾回收,但会影响对象是否“可达”——而可达性才是 GC 的唯一判定依据。
原型对象按普通对象参与回收
函数的 prototype 是一个普通对象,和其他堆中对象一样,只看它是否还能从 GC 根(如全局变量、闭包、活动执行上下文等)被访问到。如果构造函数被设为 null,且没有其他引用指向它的 prototype,那这个原型对象就会被回收。浏览器里挂在 window 或模块顶层的构造函数通常长期存活,所以它们的 prototype 很难被回收。
实例回收与原型完全无关
一个实例能否被回收,只取决于它自身是否可达,跟它的 __proto__ 指向谁没关系:
- 即使原型对象很大、方法很多,只要实例本身不可达,它立刻会被回收
- 原型对象是否回收,是另一件事——它取决于自己的引用路径,不是由实例拖着不放
-
in或hasOwnProperty这类属性查找操作,不会改变对象的可达性,也不影响 GC
原型链不构成回收屏障
原型链只是查找属性时的委托路径,并不建立强引用关系:
立即学习“Java免费学习笔记(深入)”;
- 子对象的
__proto__指向父原型,这属于单向引用,不影响父原型的生命周期 - 若父原型已不可达,哪怕子对象还活着,父原型照样被回收
- 动态模块中,显式解除对模块的引用(如
moduleRef = null),其导出的构造函数及对应prototype都可能一并回收
容易引发内存泄漏的常见误区
真正拖住对象不被回收的,往往不是原型链本身,而是隐含的强引用:
- 闭包中意外保留了对大型原型对象或其实例的引用
- 事件监听器绑定在原型方法上,但监听器被长期持有(如未清理的 DOM 事件)
- 子类构造函数中缓存了父类实例,形成“本不需要的引用链”
不复杂但容易忽略:GC 看的是引用图,不是语法结构。原型链是逻辑关系,不是内存锁链。


















