
在 JavaScript 中,向构造函数的 prototype 添加新方法后,所有已创建的实例都能立即访问该方法,因为属性查找是运行时沿原型链动态进行的,而非在实例化时静态复制。
在 javascript 中,向构造函数的 `prototype` 添加新方法后,所有已创建的实例都能立即访问该方法,因为属性查找是运行时沿原型链动态进行的,而非在实例化时静态复制。
JavaScript 的原型继承机制本质上是委托式查找(delegation-based lookup),而非拷贝式继承(copy-based inheritance)。当你执行 const s1 = new Student('John') 时,引擎并不会将 Student.prototype 上的所有方法“复制”到 s1 对象上;而是将 s1.__proto__(即内部 [[Prototype]])指向 Student.prototype 对象。此后每次访问 s1.sayGoodbye(),JavaScript 引擎会按如下顺序查找:
- 检查 s1 自身是否有 sayGoodbye 属性(自有属性);
- 若无,则沿着 s1.__proto__ → Student.prototype 查找;
- 若 Student.prototype 上存在该方法(无论添加于实例化前或后),即可成功调用;
- 若仍不存在,则继续向上查找至 Object.prototype,最终返回 undefined。
因此,以下代码完全合法且可预期:
function Student(name) {
this.name = name;
}
Student.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
const s1 = new Student('John');
s1.sayHello(); // ✅ "Hello, my name is John"
// 动态扩展原型(发生在实例创建之后)
Student.prototype.sayGoodbye = function() {
console.log(`Goodbye, my name is ${this.name}`);
};
s1.sayGoodbye(); // ✅ "Goodbye, my name is John" —— 正常工作!
⚠️ 注意事项:
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
__proto__ ≠ prototype:
obj.__proto__ 是实例对象的内部原型引用(应优先使用 Object.getPrototypeOf(obj));
Constructor.prototype 是构造函数用于初始化实例原型的“模板对象”,二者角色不同,不可混淆。不推荐直接修改内置原型(如 Array.prototype):
可能引发兼容性问题、覆盖原生方法或与未来标准冲突(例如手动实现 Array.prototype.find 后又升级到支持该方法的环境)。慎用 Object.setPrototypeOf() 修改已有对象的 [[Prototype]]:
该操作严重损害性能(V8 等引擎会失效内联缓存),MDN 明确警告其为“非常慢的操作”。如需特定原型关系,请改用 Object.create(prototype) 创建新对象。
✅ 正确实践建议:
对自定义构造函数的 prototype 进行动态增删(如插件式扩展、条件加载方法)是安全且符合语言设计意图的。只要不破坏原型链完整性,所有已有及后续实例均可共享更新后的行为。
总结一句话:原型是活的(live),不是快照(snapshot)——修改它,所有委托给它的对象即时受益。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










