JavaScript原型链是对象属性查找与继承的核心机制,通过[[Prototype]]内部属性逐级向上查找直至null;构造函数的prototype属性用于设置实例原型,ES6 class底层仍基于此机制,但需注意引用类型共享等局限。

JavaScript中的原型链是对象之间实现属性和方法共享与查找的机制,它构成了JS继承的核心基础。每个对象都有一个内部属性 [[Prototype]](可通过 __proto__ 访问,或用 Object.getPrototypeOf() 获取),指向它的原型对象;而这个原型对象本身也可能有原型,层层向上,直到为 null —— 这条链就是原型链。
原型链如何工作:属性查找规则
当访问一个对象的属性时,JS引擎会按以下顺序查找:
- 先在对象自身上查找该属性;
- 若未找到,则沿着
[[Prototype]]链向上,在原型对象中继续查找; - 一直查到原型为
null(即Object.prototype的原型)为止; - 如果整条链都找不到,结果为
undefined。
例如:arr = [1, 2],调用 arr.push(3) 时,arr 自身没有 push 方法,但它的原型是 Array.prototype,而该对象上有 push,因此调用成功。
构造函数与 prototype 属性的关系
函数对象(包括自定义构造函数)有一个显式的 prototype 属性,它是一个普通对象,默认包含一个 constructor 指回该函数。当用 new Fn() 创建实例时,实例的 [[Prototype]] 会自动指向该函数的 prototype 对象。
立即学习“Java免费学习笔记(深入)”;
这是手动构建原型链的关键入口。比如:
function Animal(name) { this.name = name; }
Animal.prototype.speak = function() { console.log(this.name + ' makes a sound'); };
const dog = new Animal('Dog');
dog.speak(); // 正常执行:'Dog makes a sound'
此时 dog.__proto__ === Animal.prototype,而 Animal.prototype.__proto__ === Object.prototype,最终 Object.prototype.__proto__ === null。
基于原型链的继承实现方式
传统“类式继承”在ES6前主要靠原型链模拟,常见做法包括:
-
直接赋值原型:让子类构造函数的
prototype指向父类实例(如Child.prototype = new Parent()),但会带来引用类型共享问题; -
组合继承(最常用):构造函数内调用父类(解决实例属性继承),再用
Object.create(Parent.prototype)设置子类原型(避免父类构造函数重复执行); -
ES6 class 的本质:虽然语法更接近传统类,但底层仍是原型链。
class B extends A会自动设置B.prototype.__proto__ === A.prototype,并确保super()正确初始化this。
原型链的局限与注意事项
原型链不是万能的,使用中需注意:
- 所有实例共享原型上的属性(尤其是数组、对象等引用类型),修改会影响其他实例;
- 无法实现多继承(一个对象只能有一个
[[Prototype]]); - 不能通过原型链访问父类的私有变量或构造函数内部的局部变量;
- 检测关系建议用
instanceof或Object.prototype.isPrototypeOf(),而非直接比较__proto__(非标准且已不推荐)。
现代开发中,配合 Object.create()、Object.setPrototypeOf() 和 class 语法,可以更安全、清晰地控制原型链结构。










