将方法挂载到构造函数的 prototype 上可实现内存高效共享:所有实例通过 proto 链访问同一函数对象,避免重复创建;实例属性优先于原型属性,但删除后自动回退至原型;原型链支持多层继承与方法复用。

把方法统一挂到构造函数的 prototype 上,是实现高效内存共享最直接有效的方式——函数只存一份,所有实例通过 __proto__ 链自动访问,避免重复创建。
把方法从构造函数里“搬”到 prototype 上
构造函数内部定义方法,每次 new 都会新建一个函数对象,造成冗余:
- 错误写法(每个实例独占一份):
function Person(name) {
this.name = name;
this.say = function() { console.log(this.name); };
} - 正确写法(所有实例共用一份):
function Person(name) {
this.name = name;
}
Person.prototype.say = function() { console.log(this.name); };
验证: new Person('a').say === new Person('b').say 返回 true,说明指向同一函数对象。
理解 __proto__ 与 prototype 的对应关系
每个实例对象都有隐式属性 __proto__,它在 new 时自动指向其构造函数的 prototype:
-
const p = new Person('Tom');
p.__proto__ === Person.prototype → true - p.say() 实际查找路径是:p → p.__proto__ → Person.prototype
- 无需手动设置 __proto__,JS 引擎已自动完成绑定
注意属性/方法查找的优先级规则
实例自身属性或方法存在时,会“遮蔽”原型上的同名成员,但不破坏共享机制:
- 若执行 p.say = function() { console.log('own'); },再调 p.say() 就不会走原型链
- 想临时绕过实例、强制调原型方法,可用:Person.prototype.say.call(p)
- 删掉实例属性后,原型上的方法自然“浮现”:delete p.say; 再调就恢复走原型
多层原型链支持更灵活的复用结构
原型本身也是对象,它也有自己的 __proto__,可继续向上链接:
- Person.prototype.__proto__ === Object.prototype → true
- 所以 p.toString() 虽未定义在 Person.prototype,也能沿链找到 Object.prototype.toString
- 这种层级结构让继承、兜底行为和组件方法共享(如 Vue/React)成为可能











