原型属性通过__proto__链共享,方法和原始值适合放prototype,引用类型直接放置会导致实例间数据污染,应初始化在构造函数中或用懒加载隔离。

原型对象上的属性能被实例共享,靠的是 JavaScript 的属性查找机制——不是复制,而是沿 __proto__ 链向上查找。只要属性定义在构造函数的 prototype 上,所有实例就能“看到”它,但是否真正“共用”,取决于值的类型和访问方式。
哪些属性适合放在 prototype 上共享
适合共享的,是那些不需要每个实例独立副本的内容:
-
方法函数:比如
Person.prototype.sayHello = function() { ... },函数对象本身不可变,所有实例调用的是同一份代码 -
原始值属性:如
Person.prototype.species = 'Homo sapiens',字符串、数字、布尔值在读取时会自动复制,不会互相影响 -
冻结的只读对象:例如
Person.prototype.config = Object.freeze({ api: '/v1' }),确保后续无法修改,避免意外污染
为什么数组或对象不能直接挂 prototype
引用类型(数组、普通对象、日期等)一旦写在 prototype 上,所有实例访问的是同一块内存地址:
比如 function Task() {}Task.prototype.items = [];const a = new Task();const b = new Task();a.items.push('x');console.log(b.items); // ['x'] —— b 被意外修改
这是因为 a.items 和 b.items 指向同一个数组,而原型上没有同名自有属性时,读写操作都落在原型对象上。
如何让引用类型既可复用又不共享
关键不是“能不能放原型”,而是“初始化时机”:
- 把引用类型初始化写在构造函数或
constructor里:this.items = [],保证每次new都生成新实例 - 若需延迟初始化,可在原型方法中检查:
if (!this.data) this.data = {},实现懒加载且隔离 - 多构造函数想共用一套方法?可让它们指向同一原型对象:
B.prototype = A.prototype,但各自构造函数仍须初始化自己的数据属性
实例属性与原型属性的优先级关系
实例自身有同名属性时,会遮蔽原型上的同名属性:
-
p.name = 'Alice'后,p.name就不再走原型链 -
delete p.name后,再次访问p.name就恢复从原型读取 - 想强制调用原型方法?用
Parent.prototype.method.call(p)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











