JavaScript 采用原型链继承而非类继承,对象通过 proto 链接原型实现属性和方法共享;new 实例时自动赋值 proto = 构造函数.prototype;Object.create() 是安全建立原型链的推荐方式;class 是基于原型链的语法糖;原型链仅影响读取,赋值会遮蔽原型属性。

JavaScript 中没有类继承,只有原型链继承——对象通过 __proto__ 链接到另一个对象(即它的原型),从而共享属性和方法。所谓“原型链”,就是从一个对象出发,沿着 __proto__ 一层层向上查找,直到到达 null 的过程。
为什么 new 一个函数会得到有原型的对象?
因为函数的 prototype 属性会被自动赋给实例的 __proto__。这个机制是原型链继承的起点。
-
function Person(name) { this.name = name; }定义后,Person.prototype默认是一个空对象,且自带constructor指向Person -
const p = new Person('Alice')创建实例时,引擎自动执行p.__proto__ = Person.prototype - 后续对
p.toString()的调用,实际是沿p.__proto__ → Person.prototype.__proto__ → Object.prototype查找,最终落到Object.prototype.toString
如何手动建立原型链关系?
用 Object.setPrototypeOf() 或直接赋值 __proto__(不推荐)可显式设置原型,但更常见、更安全的是用 Object.create()。
const animal = {
eats: true,
walk() { console.log('walking'); }
};
const rabbit = Object.create(animal);
rabbit.jumps = true;
console.log(rabbit.eats); // true ← 来自 animal
rabbit.walk(); // 'walking' ← 来自 animal
-
Object.create(animal)创建的新对象,其__proto__直接指向animal - 不能用
{}.__proto__ = animal:虽然部分环境支持,但它是非标准、不可靠的写法 - 若需兼容老环境(如 IE8),应避免
Object.create,改用构造函数 +.prototype模拟
class 语法糖背后还是原型链吗?
是的。class 只是语法糖,所有行为仍基于原型链,包括 extends、静态方法、super 调用。
立即学习“Java免费学习笔记(深入)”;
class Animal {
constructor(name) { this.name = name; }
speak() { console.log(`${this.name} makes a sound`); }
}
class Dog extends Animal {
constructor(name, breed) {
super(name);
this.breed = breed;
}
bark() { console.log('Woof!'); }
}
const d = new Dog('Max', 'Golden');
d.speak(); // 'Max makes a sound'
d.bark(); // 'Woof!'
console.log(d.__proto__ === Dog.prototype); // true
console.log(Dog.prototype.__proto__ === Animal.prototype); // true
-
Dog.prototype.__proto__指向Animal.prototype,构成链式继承 - 静态方法(如
Dog.create())挂在Dog函数本身上,不参与实例原型链 -
super在方法中实际访问的是this.__proto__.__proto__对应的方法(严格说是[[HomeObject]]决定的,但效果等价)
真正容易被忽略的是:原型链只影响「读取」,赋值操作永远作用于当前对象自身。比如 d.eats = false 不会修改 Animal.prototype.eats,而是在 d 上新建一个同名自有属性——这是原型链“遮蔽”(shadowing)的典型表现,也是调试时属性突然不生效的常见原因。










