原型链是JavaScript对象继承的核心机制,通过[[Prototype]]内部槽隐式连接对象,属性查找沿链向上直至null;Object.create()用于安全设置原型,Object.setPrototypeOf()应避免热路径使用。

原型链是 JavaScript 中实现对象继承的核心机制,不是语法糖,而是运行时对象间隐式连接的真实引用关系。
原型链的本质:每个对象都有一个 [[Prototype]] 内部槽
这个内部槽指向另一个对象(即它的原型),查找属性或方法时,若当前对象没有该属性,引擎会沿着 [[Prototype]] 链向上逐级查找,直到找到或到达 null(链的终点)。
-
Object.prototype的[[Prototype]]是null,它是绝大多数对象原型链的终点 -
obj.__proto__是访问[[Prototype]]的非标准但广泛支持的方式;标准方式是Object.getPrototypeOf(obj) -
function.prototype是函数对象独有的属性,它被赋给用该函数创建的实例的[[Prototype]](仅限new调用)
用 function 构造函数模拟“类继承”时的原型链设置
传统方式依赖手动修正 Child.prototype 的 [[Prototype]],否则子类无法继承父类原型上的方法。
function Parent(name) {
this.name = name;
}
Parent.prototype.sayHello = function() {
return `Hello, ${this.name}`;
};
function Child(name, age) {
Parent.call(this, name); // 继承实例属性
this.age = age;
}
// 关键一步:让 Child.prototype 的 [[Prototype]] 指向 Parent.prototype
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child; // 修复 constructor 指针
const c = new Child('Alice', 10);
console.log(c.sayHello()); // "Hello, Alice" —— 成功从 Parent.prototype 查找
- 漏掉
Object.create(Parent.prototype),Child.prototype就只是个空对象,不继承任何方法 - 漏掉
constructor = Child,c.constructor会错误地指向Parent - ES6
class语法底层仍走这套逻辑,只是自动处理了上述两步
Object.setPrototypeOf() 和 Object.create() 的实际差异
二者都能建立原型链接,但使用场景和性能影响不同:
立即学习“Java免费学习笔记(深入)”;
-
Object.create(proto)创建一个新对象,并将其[[Prototype]]设为proto;适合初始化原型对象(如上例中重设Child.prototype) -
Object.setPrototypeOf(obj, proto)直接修改已有对象的[[Prototype]];会触发引擎对obj的隐藏类失效,显著影响性能,应避免在热路径中调用 - 现代代码中,优先用
Object.create()做一次性原型链搭建,而非动态改写
箭头函数、Object.assign() 和原型链无关
它们不参与原型链构建:
- 箭头函数没有自己的
prototype属性,不能用new调用,自然不产生原型链关系 -
Object.assign(target, ...sources)只是浅拷贝可枚举自有属性,不会复制[[Prototype]],也不会建立原型连接 - 想“继承”多个对象的行为?得靠组合(mixin)、代理(
Proxy)或显式委托调用,不是靠原型链自动合并
真正容易被忽略的是:原型链只在读取属性时起作用;写入或删除操作始终发生在目标对象自身,不会顺着链向上。这意味着看似“继承”的属性,一旦被子对象赋值,就变成了自有属性,遮蔽了原型上的同名属性——这是很多动态覆盖逻辑出 bug 的根源。










