JavaScript原型链是通过__proto__连接的属性查找路径,实例的__proto__指向构造函数的prototype;Object.create(Person.prototype)确保继承安全,避免共享原型;原型链动态更新,新增方法即时生效。

JavaScript 原型链不是“类继承”的翻版,而是一条由 __proto__ 连起来的、用于属性查找的隐式路径——对象自己没有的属性,就顺着这条链往上问“你有吗?”,直到问到 null 为止。
为什么访问 obj.method() 能成功,但 obj 上根本没定义它?
因为 JavaScript 引擎在调用前会自动走一遍原型链查找:
- 先查
obj自身是否有method - 没有 → 查
obj.__proto__(即构造函数的prototype) - 还没找到 → 继续查
obj.__proto__.__proto__(通常是Object.prototype) - 再往上是
null,停止查找,报TypeError: obj.method is not a function
这个过程完全自动,不写 super、不显式调用父级,纯靠链式委托。
prototype 和 __proto__ 到底谁指向谁?
一句话记牢:实例的 __proto__ 指向构造函数的 prototype。别反了,也别混成同一个东西:
立即学习“Java免费学习笔记(深入)”;
-
prototype是函数才有的属性(比如Person.prototype),它是给未来实例共享方法用的“模板对象” -
__proto__是每个对象都有的内部链接(非标准但普遍支持),它才是运行时真正被引擎用来跳转的指针 - ES6 后推荐用
Object.getPrototypeOf(obj)替代直接读obj.__proto__,更规范
function Person(name) {
this.name = name;
}
Person.prototype.sayHi = function() { return `Hi, ${this.name}`; };
const p = new Person('Alice');
console.log(p.__proto__ === Person.prototype); // true
console.log(Object.getPrototypeOf(p) === Person.prototype); // true
手动实现继承时,Object.create(Person.prototype) 为什么不能省?
直接写 Dog.prototype = Person.prototype 是危险操作——这会让 Dog 和 Person 共享同一份原型对象,改一个就全改了:
- 错误写法:
Dog.prototype = Person.prototype→Dog.prototype.constructor变成Person,且所有Person实例也会“意外获得”Dog新增的方法 - 正确写法:
Dog.prototype = Object.create(Person.prototype)→ 创建一个干净的、以Person.prototype为原型的新对象,再补上Dog.prototype.constructor = Dog - 现代替代:用
class Dog extends Person,但要知道它只是语法糖,底层仍是这套原型链逻辑
哪些地方最容易踩坑?
原型链看着轻巧,实际几个细节一错就连锁崩坏:
- 忘了重置
constructor:用Object.create后,Dog.prototype.constructor指向Person,影响instance.constructor判断和序列化 - 在原型上直接改引用类型(如数组、对象):所有实例共享同一份内存,一个 push,全部变
- 误以为
for...in遍历的是“自身属性”:它会遍历整个原型链上的可枚举属性,要用hasOwnProperty过滤 - 用
delete obj.prop删除原型链上的属性?删不掉——delete只作用于对象自身,对原型链无效
最常被忽略的一点:原型链是动态的。你在 Person.prototype 上新增方法,所有已存在的 Person 实例立刻就能用——这不是魔法,是引擎每次访问都实时查找的结果。











