JavaScript 是一门基于原型(Prototype) 的语言,而非传统的类(Class)语言(ES6 的 class 只是语法糖)。
prototype 属性(原型对象),这个对象默认包含两个核心属性:
constructor:指向该函数本身(比如 Person.prototype.constructor === Person)。__proto__:指向该原型对象的原型(即上一级原型)。__proto__ 属性(ES6 中可通过 Object.getPrototypeOf() 访问),它会指向创建该实例的构造函数的 prototype。当你访问一个对象的属性/方法时,JS 会先在对象自身查找:
__proto__ 向上查找其原型对象的属性/方法;Object.prototype(原型链的顶端);Object.prototype 还没找到,就返回 undefined。这条由 __proto__ 串联起来的查找链条,就是原型链。
// 1. 定义构造函数
function Person(name) {
this.name = name; // 实例自身属性
}
// 2. 给构造函数的原型添加方法(所有实例共享)
Person.prototype.sayHello = function () {
console.log(`Hello, I'm ${this.name}`);
};
// 3. 创建实例
const tom = new Person("Tom");
// 4. 验证原型关系
console.log(tom.__proto__ === Person.prototype); // true:实例的__proto__指向构造函数的prototype
console.log(Person.prototype.__proto__ === Object.prototype); // true:Person原型的原型指向Object原型
console.log(Object.prototype.__proto__); // null:原型链的顶端
// 5. 原型链查找演示
tom.sayHello(); // 自身没有sayHello,向上找Person.prototype,执行 → Hello, I'm Tom
console.log(tom.toString()); // 自身/Person.prototype都没有,向上找Object.prototype的toString方法 → [object Object]
console.log(tom.age); // 整条原型链都没有,返回undefined
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
// 等价于 Person.prototype.sayHello
console.log(`Hello, I'm ${this.name}`);
}
}
const tom = new Person("Tom");
console.log(tom.__proto__ === Person.prototype); // 依然为true,class本质还是原型
sayHello 方法,所有 Person 实例都能用,且只存一份)。__proto__ → 构造函数的 prototype → Object.prototype → null,这就是完整的原型链。__proto__ 向上查,直到 Object.prototype,找不到则返回 undefined。class 只是原型链的语法糖,底层逻辑不变。