跳到主要内容

JavaScript 原型

提示
  1. 原型的基本概念:在JavaScript中,每个函数和对象默认具有名为prototype的属性。通过原型可以向构造函数添加属性和方法,这些属性和方法被构造函数创建的所有对象继承。
  2. 原型继承:使用原型添加到构造函数中的属性或方法,由该构造函数创建的所有对象实例都会继承这些属性或方法。
  3. 原型链:如果对象尝试访问在其构造函数和原型对象中都存在的属性,该对象会优先从构造函数中获取该属性。

在学习原型之前,请确保查看这些教程:

如您所知,可以使用对象构造函数在 JavaScript 中创建对象。例如,

// 构造函数
function Person() {
(this.name = "John"), (this.age = 23);
}

// 创建对象
const person1 = new Person();
const person2 = new Person();

在上述示例中,function Person() 是一个对象构造函数。我们已经从它创建了两个对象 person1person2

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";

然后对象 person1person2Person 构造函数的原型属性继承了 gender 属性。

因此,两个对象 person1person2 都可以访问 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__ 已被弃用,您应该避免使用它。