JavaScript 使用基于原型的继承模型,这与许多其他语言的基于类的继承不同。理解原型是掌握 JavaScript 的关键。
原型对象 (Prototype): 每个 JavaScript 对象都有一个隐藏的 [[Prototype]]
属性,指向它的原型对象。
原型链: 当访问一个对象的属性时,如果对象本身没有该属性,JavaScript 会沿着原型链向上查找。
// 1. 通过 __proto__ 属性(非标准,但广泛实现)
obj.__proto__
// 2. 通过 Object.getPrototypeOf()(推荐方式)
Object.getPrototypeOf(obj)
// 3. 设置原型
Object.setPrototypeOf(obj, prototype)
function Person(name) {
this.name = name;
}
// 添加到构造函数的原型上的属性和方法会被所有实例共享
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person1 = new Person('Alice');
person1.sayHello(); // "Hello, my name is Alice"
const parent = {
value: 2,
method() {
return this.value + 1;
}
};
const child = {
__proto__: parent, // 设置原型
value: 3
};
console.log(child.method()); // 4
// 1. child 查找 method
// 2. 在 child 上找不到,去原型 parent 上找
// 3. 找到后执行,this 指向 child
Object.prototype
: 几乎所有对象的原型链顶端Array.prototype
: 数组方法所在的原型Function.prototype
: 函数方法所在的原型ES6 引入了 class 语法,但它只是原型继承的语法糖:
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
console.log(`Hello, my name is ${this.name}`);
}
}
// 等同于
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
Object.create(proto)
: 创建一个新对象,使用现有对象作为新对象的原型Object.getPrototypeOf(obj)
: 返回指定对象的原型Object.setPrototypeOf(obj, prototype)
: 设置对象的原型obj.hasOwnProperty(prop)
: 检查属性是否是对象自身的(非继承的)prop in obj
: 检查属性是否在对象或其原型链上理解 JavaScript 的原型系统对于编写高效、可维护的代码至关重要,也是理解 JavaScript 面向对象编程的基础。