原型上放方法能节省内存,因为函数只创建一次并被所有实例共享,避免每个实例重复存储相同函数。

把方法定义在构造函数的 prototype 上,所有实例就能共用同一份函数代码,避免每个对象都存一份副本,内存自然就省下来了。
为什么原型上放方法能节省内存
每次用 new 创建实例时,如果在构造函数里写 this.sayName = function() {},每个实例都会在堆中分配一个独立的函数对象。100 个实例,就有 100 份 sayName 函数——内容一模一样,纯属浪费。
而写在 Person.prototype.sayName = function() {} 中,函数只创建一次,存在原型对象里。所有实例通过 __proto__ 链访问它,共享同一个内存地址。
- 验证方式:打印 per1.sayName === per2.sayName,结果为 true
- 实例自身没有该方法时,会自动沿原型链向上查找
- 实例上同名属性或方法会屏蔽原型上的对应成员(这是正常优先级行为)
正确挂载方法到原型的两种写法
推荐统一在构造函数外部操作 prototype,避免覆盖默认 constructor。
- 单个添加:Person.prototype.sayName = function() { console.log(this.name); };
- 批量重写(需手动修复 constructor):
Person.prototype = {
constructor: Person,
sayName() { console.log(this.name); },
walk() { console.log(this.name + ' is walking'); }
};
漏掉 constructor: Person 会导致实例的 constructor 指向 Object,影响类型判断和 instanceof 行为。
注意属性与方法的共享边界
原型适合放**方法**和**不变的默认值**(如 Person.prototype.species = 'Homo sapiens'),但不适合放引用类型属性(如数组、对象)。
- 如果写 Person.prototype.hobbies = [],所有实例会共用这个空数组——一人 push,全员受影响
- 实例自有属性(this.name)始终优先于原型成员,互不干扰
- 想强制调用原型方法,可用 Person.prototype.sayName.call(this)
现代写法更简洁安全
ES6 的 class 语法本质仍是原型机制,但自动处理了 constructor 和方法挂载:
class Person {
constructor(name) { this.name = name; }
sayName() { console.log(this.name); }
}
编译后,sayName 依然落在 Person.prototype 上,所有实例共享,且无 constructor 被覆盖风险。










