当我们在 JavaScript 中创建一个对象时,它会自动继承一个称为“原型”的对象。如果该对象访问一个属性或方法,但在自己的属性列表中找不到,它会沿着原型链向上查找,直到找到该属性或方法为止。在本篇文章中,我们将深入探讨 JavaScript 中的原型与原型链。
什么是原型?
在 JavaScript 中,每个对象都有一个原型,它定义了对象的默认属性和方法。如果我们尝试访问一个对象的属性或方法,但该属性或方法不存在于该对象本身的属性列表中,JavaScript 引擎就会沿着对象的原型链向上查找,直到找到该属性或方法为止。
在 JavaScript 中,我们可以使用构造函数来创建一个对象。构造函数是一个普通的函数,它可以使用 new
关键字来创建一个实例对象。例如:
function Person(name, age) {
this.name = name;
this.age = age;
}
const person = new Person("Alice", 30);
在上面的代码中,我们定义了一个 Person
构造函数,它接受两个参数 name
和 age
,并使用 this
关键字将它们赋值给新创建的对象。我们可以使用 new
关键字来创建一个 Person
实例,并将其存储在 person
变量中。
每个 JavaScript 对象都有一个 prototype
属性,它指向该对象的原型。在上面的代码中,我们可以使用 Person.prototype
来访问 Person
的原型对象。
原型链
原型链是 JavaScript 中一个非常重要的概念,它描述了对象之间的继承关系。每个对象都有一个原型链,它是一个指向其他对象的链表。当我们访问一个对象的属性或方法时,JavaScript 引擎会首先查找对象本身的属性列表,如果找不到,它就会沿着原型链向上查找,直到找到该属性或方法为止。
在 JavaScript 中,原型链是通过 prototype
属性实现的。当我们创建一个对象时,它会自动继承其构造函数的原型对象。如果该对象的原型对象也有一个原型对象,那么它也会继承该对象的原型对象,以此类推,形成一个链表。
以下是一个简单的原型链示例:
function Animal(name) {
this.name = name;
}
Animal.prototype.sayName = function() {
console.log(`My name is ${
this.name}.`);
};
function Dog(name, breed) {
Animal.call(this, name);
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.sayBreed = function() {
console.log(`I am a ${
this.breed}.`);
};
const dog = new Dog("Fido", "Labrador");
dog.sayName(); // 输出 "My name is Fido."
dog.sayBreed(); // 输出 "I am a Labrador."
在上面的代码中,我们定义了两个构造函数 Animal
和 Dog
。Animal
构造函数定义了一个 name
属性和一个 sayName
方法,而 Dog
构造函数使用 call
方法调用 Animal
构造函数,并定义了一个 breed
属性和一个 sayBreed
方法。
我们将 Dog
的原型对象设置为 Animal
的原型对象,这样 Dog
就继承了 Animal
的属性和方法。我们还将 Dog
的原型对象的 constructor
属性设置为 Dog
,以便在实例化 Dog
对象时能够正确地调用 Dog
构造函数。
当我们创建一个 Dog
实例时,它会自动继承 Animal
的原型对象。因此,我们可以在 dog
对象上调用 sayName
和 sayBreed
方法,并且它们都能正常工作。
总结
JavaScript 的原型和原型链是非常重要的概念,它们使得 JavaScript 可以实现面向对象编程,并且能够方便地实现继承。每个对象都有一个原型,它定义了对象的默认属性和方法。当我们访问一个对象的属性或方法时,JavaScript 引擎会沿着对象的原型链向上查找,直到找到该属性或方法为止。通过设置构造函数的原型对象,我们可以实现对象之间的继承关系,并且可以方便地重用代码。