直接往构造函数的 prototype 上添加方法是最标准、最轻量的属性扩展方式,所有实例(包括已创建和后续新建的)自动共享该方法,节省内存且支持动态扩展;需避免直接污染实例或滥用内置原型。

直接往构造函数的 prototype 上添加方法,是最标准、最轻量的属性扩展方式。它不修改已有实例本身,而是让所有实例(包括已创建和后续新建的)自动获得新能力,共享同一份逻辑,节省内存。
给构造函数 prototype 添加方法
这是最常用也最推荐的做法。只要把函数挂到构造函数的 prototype 属性上,所有该类型的实例就能立即调用:
- 例如为
Person添加打招呼方法:function Person(name) { this.name = name; }<br>Person.prototype.sayHello = function() { return `Hi, I'm ${this.name}`; };<br>const p1 = new Person('Tom');<br>console.log(p1.sayHello()); // "Hi, I'm Tom" - 新增的方法能访问
this,也就是当前实例,因此可读写实例自身的属性 - 即使实例
p1在sayHello定义前就已创建,也能立刻使用——因为查找机制走的是原型链
动态扩展已存在对象的行为
运行时随时可以补加方法,不影响已有实例:
- 先创建实例:
const arr = [1, 2, 3]; - 再扩展内置原型(谨慎使用):
Array.prototype.last = function() { return this[this.length - 1]; }; - 此时
arr.last()就能直接调用,无需重建数组 - 注意:扩展
Array、String等内置原型时,建议加前缀(如myLast)或先检查是否已存在,避免冲突
用 Object.defineProperty 精确控制属性行为
当需要设定属性是否可枚举、可写、可配置时,不能简单赋值,得用 Object.defineProperty:
- 比如添加一个只读的
fullName计算属性:Object.defineProperty(Person.prototype, 'fullName', {<br> get() { return this.name || ''; },<br> enumerable: true,<br> configurable: true<br>}); -
enumerable: false可防止该属性出现在for...in或Object.keys()中 -
writable: false和configurable: false能进一步锁定属性行为
避免直接污染实例,优先走原型链
扩展目标是让多个实例共享能力,不是只改某一个对象:
- ❌ 错误做法:
p1.sayHello = function() {...}→ 只作用于p1,其他实例无感知 - ✅ 正确做法:
Person.prototype.sayHello = function() {...}→ 所有Person实例都受益 - 如果某个实例需要特殊行为,可单独覆盖:
p1.sayHello = function() { ... },这会屏蔽原型上的同名方法,但不影响其他实例


















