JavaScript 原型
- 原型的基本概念:在JavaScript中,每个函数和对象默认具有名为
prototype
的属性。通过原型可以向构造函数添加属性和方法,这些属性和方法被构造函数创建的所有对象继承。 - 原型继承:使用原型添加到构造函数中的属性或方法,由该构造函数创建的所有对象实例都会继承这些属性或方法。
- 原型链:如果对象尝试访问在其构造函数和原型对象中都存在的属性,该对象会优先从构造函数中获取该属性。
在学习原型之前,请确保查看这些教程:
如您所知,可以使用对象构造函数在 JavaScript 中创建对象。例如,
// 构造函数
function Person() {
(this.name = "John"), (this.age = 23);
}
// 创建对象
const person1 = new Person();
const person2 = new Person();
在上述示例中,function Person()
是一个对象构造函数。我们已经从它创建了两个对象 person1
和 person2
。
JavaScript 原型
在 JavaScript 中,每个函数和对象默认都有一个名为 prototype 的属性。例如,
function Person() {
(this.name = "John"), (this.age = 23);
}
const person = new Person();
// 检查原型值
console.log(Person.prototype); // { ... }
在上面的示例中,我们试图访问 Person
构造函数的 prototype 属性。
由于原型属性当前没有值,它显示一个空对象 { ... }
。
原型继承
在 JavaScript 中,原型可以用来向构造函数添加属性和方法。对象从原型继承属性和方法。例如,
// 构造函数
function Person() {
(this.name = "John"), (this.age = 23);
}
// 创建对象
const person1 = new Person();
const person2 = new Person();
// 向构造函数添加属性
Person.prototype.gender = "male";
// Person 的原型值
console.log(Person.prototype);
// 从原型继承属性
console.log(person1.gender);
console.log(person2.gender);
输出
{
gender: "male";
}
male;
male;
在上述程序中,我们使用以下代码向 Person
构造函数添加了一个新属性 gender
:
Person.prototype.gender = "male";
然后对象 person1
和 person2
从 Person
构造函数的原型属性继承了 gender
属性。
因此,两个对象 person1
和 person2
都可以访问 gender 属性。
注意:向对象构造函数添加属性的语法是:
objectConstructorName.prototype.key = "value";
原型用于向从构造函数创建的所有对象提供额外的属性。
使用原型向构造函数添加方法
您还可以使用原型向构造函数添加新方法。例如,
// 构造函数
function Person() {
(this.name = "John"), (this.age = 23);
}
// 创建对象
const person1 = new Person();
const person2 = new Person();
// 向构造函数添加一个方法
Person.prototype.greet = function () {
console.log("你好" + " " + this.name);
};
person1.greet(); // 你好 John
person2.greet(); // 你好 John
在上述程序中,使用原型向 Person
构造函数添加了一个新方法 greet
。
更改原型
如果更改了原型的值,则所有新创建的对象都将具有更改后的属性值。所有之前创建的对象将具有之前的值。例如,
// 构造函数
function Person() {
this.name = "John";
}
// 添加一个属性
Person.prototype.age = 20;
// 创建一个对象
const person1 = new Person();
console.log(person1.age); // 20
// 更改原型的属性值
Person.prototype = { age: 50 };
// 创建新对象
const person3 = new Person();
console.log(person3.age); // 50
console.log(person1.age); // 20
注意:您不应该修改标准 JavaScript 内置对象(如字符串、数组等)的原型。这被认为是一种不良实践。
JavaScript 原型链
如果对象尝试访问在构造函数和原型对象中都存在的同一属性,对象将从构造函数中取得该属性。例 如,
function Person() {
this.name = "John";
}
// 添加属性
Person.prototype.name = "Peter";
Person.prototype.age = 23;
const person1 = new Person();
console.log(person1.name); // John
console.log(person1.age); // 23
在上述程序中,构造函数和构造函数的原型属性中都声明了 name 属性。
当程序执行时,person1.name
在构造函数中查找名为 name
的属性。由于构造函数具有值为 'John'
的 name 属性,对象从该属性中取值。
当程序执行时,person1.age
在构造函数中查找名为 age
的属性。由于构造函数没有 age
属性,程序查看构造函数的原型对象,对象从原型对象继承属性(如果可用)。
注意:您也可以从对象访问构造函数的原型属性。
function Person() {
this.name = "John";
}
// 添加原型
Person.prototype.age = 24;
// 创建对象
const person = new Person();
// 访问原型属性
console.log(person.__proto__); // { age: 24 }
在上述示例中,使用 person
对象访问原型属性,使用 __proto__
。然而,__proto__
已被弃用,您应该避免使用它。