构造函数内初始化引用类型属性可避免共享,prototype适合放方法和不可变常量;继承时应用Object.create替代new Parent防止原型链污染。

构造函数本身不会导致属性共享问题,真正引发问题的是把可变数据(比如数组、对象)直接挂到 prototype 上。要避免属性共享,关键在于分清哪些该放实例里、哪些能放原型上。
实例属性必须在构造函数内初始化
所有需要每个实例独立拥有的数据,尤其是引用类型,一定要在构造函数内部用 this 赋值。
- 字符串、数字等基本类型可以放原型上(但通常没必要,语义不清)
- 数组、对象、日期、正则等引用类型绝不能写在 Person.prototype.hobbies = [] 这类位置
- 正确做法是:在构造函数里为每个实例创建专属副本
例如:
function Person(name) {this.name = name;
this.hobbies = []; // ✅ 每个实例都有自己的数组
this.profile = { level: 1 }; // ✅ 独立对象
}
方法和不可变常量适合放在 prototype 上
函数和只读的基本类型值(如字符串字面量、布尔值)可以安全地定义在原型上,它们被所有实例共享,且不会相互干扰。
立即学习“Java免费学习笔记(深入)”;
- sayHello() 这类行为逻辑,放 prototype 节省内存又无副作用
- species = 'Homo sapiens' 这种固定值也可以放,但要注意别误改
- 避免把 config = { timeout: 5000 } 这种配置对象放 prototype —— 它是引用类型,会被共用
警惕继承时的原型链污染
子类设置 Child.prototype = new Parent() 会把父类构造函数中创建的引用属性也变成共享的。
- 比如父类里 this.tags = [],所有子类实例就会共用一个数组
- 推荐用 Object.create(Parent.prototype) 替代 new Parent() 来设置子类原型
- 再手动调用 Parent.call(this, ...) 初始化实例自有属性,确保引用类型不共享
构造函数参数要做基础校验
不是所有传入的数据都可信,构造函数应主动拦截非法输入,防止后续出错。
- 检查必填字段是否为空或 undefined
- 对传入的对象做浅拷贝或结构验证,避免外部修改影响实例状态
- 不要在构造函数里执行异步操作或复杂业务逻辑,专注初始化


















