JavaScript中应将公共方法和只读值类型属性放原型上以节省内存,但引用类型属性必须在构造函数内初始化,避免实例间意外共享。

在 JavaScript 中,把方法和**只读的、值类型的共享属性**放到原型对象上,是避免内存浪费的核心做法。关键不是“能不能加”,而是“加什么、怎么加才安全”。
公共方法必须放 prototype 上
构造函数内部定义方法,每次 new 都会新建一份函数对象,造成重复占用内存。应统一挂到 prototype:
- 所有实例共用同一份函数,节省大量内存
- 方法中的 this 仍正确指向调用它的实例
- 支持运行时动态修改,影响所有已有实例
示例:
function Person(name) {this.name = name;
}
Person.prototype.sayHi = function() {
console.log('Hi, ' + this.name);
};
值类型共享属性可以放心加
字符串、数字、布尔值等原始类型,在 prototype 上定义是安全的:
- 它们不可变,修改需重新赋值,不会污染其他实例
- 实例读取时若自身无该属性,自动沿原型链向上取值
例如:
Person.prototype.species = 'Homo sapiens';Person.prototype.maxAge = 120;
引用类型属性绝不能直接挂 prototype
数组、对象、正则等引用类型一旦放在 prototype 上,所有实例将共享同一个内存地址:
- p1.hobbies.push('coding') → p2.hobbies 也会多出一项
- 这是典型的隐式副作用,极易引发线上 bug
- 正确做法:在构造函数内为每个实例单独初始化
错误写法(❌):
Person.prototype.hobbies = [];正确写法(✅):
function Person(name) {this.name = name;
this.hobbies = [];
}
添加方式推荐 Object.assign 或逐个赋值
避免直接覆盖整个 prototype,否则会丢失 constructor 指向:
- 用 Object.assign(Person.prototype, { ... }) 批量注入
- 或逐个写 Person.prototype.methodA = ...
- 若必须重写 prototype,记得手动补回 constructor
例如:
Person.prototype = {constructor: Person,
sayHi() { /* ... */ }
};











