构造函数内定义方法会为每个实例创建独立函数副本,浪费内存;应将通用方法挂载到prototype上实现共享,实例属性保留在构造函数内,注意重写prototype时修复constructor指向。

构造函数内部定义方法,会导致每个实例都拥有独立的一份函数副本,浪费内存;用原型(prototype)把方法挂载到构造函数的原型对象上,就能让所有实例共享同一个函数,从根本上避免重复创建。
为什么构造函数里定义方法会浪费内存
每次调用 new 创建新实例时,构造函数内部的 this.xxx = function() {...} 都会生成一个全新的函数对象。即使逻辑完全一样,它们在内存中也是彼此独立的:
// 每个实例的 sayName 都是不同函数
function Person(name) {
this.name = name;
this.sayName = function() { return this.name; };
}
const p1 = new Person('Alice');
const p2 = new Person('Bob');
console.log(p1.sayName === p2.sayName); // false ← 两个不同函数
怎么用 prototype 把方法移到原型上
把方法定义在构造函数的 prototype 属性上,所有实例通过原型链自动共享它:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
- 写法:直接赋值
Constructor.prototype.methodName = function() {...} - 效果:实例访问该方法时,自身找不到就自动去原型上查找
- 验证:
p1.sayName === p2.sayName返回 true
// 改进后
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() { return this.name; };
const p1 = new Person('Alice');
const p2 = new Person('Bob');
console.log(p1.sayName === p2.sayName); // true ← 同一个函数
属性和方法的合理分工
保持代码清晰高效的关键是区分数据与行为:
- 实例属性(如
name、age)放在构造函数内 —— 每个对象需要自己的值 - 通用方法(如
sayName()、eat())统一放到prototype上 —— 所有实例复用一份 - 避免混用:不要在
prototype上放可变对象(如数组、对象字面量),否则多个实例会意外共享同一份引用
注意 constructor 指针别丢失
如果用对象字面量重写整个 prototype,默认的 constructor 会指向 Object,需手动修复:
// ❌ 错误写法(丢失 constructor)
Person.prototype = {
sayName() { return this.name; }
};
// ✅ 正确写法
Person.prototype = {
constructor: Person,
sayName() { return this.name; }
};










