原型模式是一种在许多相同类型的对象之间共享属性的有用方法。 原型prototype
是 JavaScript 原生的对象,对象可以通过原型链__proto__
访问。
在应用程序中,我们经常需要创建许多相同类型的对象。 一个有用的方法是创建一个 ES6 类的多个实例。
假设我们想创造很多狗! 在我们的例子中,狗不能做很多事:它们只有一个名字,而且它们可以吠叫!
类 class
|
|
原型 prototype
请注意,构造函数如何包含 name 属性,而类本身包含 bark 属性。
使用 ES6 类时,在类本身上定义的所有属性(在本例中为 bark)都会自动添加到原型prototype
中。
可以通过访问构造函数上的 prototype 属性直接查看原型,或者通过任何实例上的 __proto__
属性。
|
|
__proto__
在构造函数的任何实例上的值,是对构造函数原型的直接引用!
每当我们尝试直接访问对象上不存在的属性时,JavaScript 将沿着原型链向下查看该属性是否在原型链中可用。
在处理应该可以访问相同属性的对象时,原型模式非常强大。
可以简单地将属性添加到原型,而不是每次都创建属性的副本,因为所有实例都可以访问原型对象。
由于所有实例都可以访问原型,因此即使在创建实例之后,也可以轻松地向原型添加属性。
狗不仅应该会吠,还应该会玩!可以通过向原型添加 play 属性来实现这一点。
|
|
原型链 __proto__
原型链表示可能不止一个步骤。 的确! 到目前为止,我们只看到了如何访问在 __proto__
引用的第一个对象上直接可用的属性。 然而,原型本身也有一个 __proto__
对象!
让我们创造另一种类型的狗,超级狗! 这只狗应该继承普通狗的一切,但它也应该会飞。 我们可以通过扩展 Dog 类并添加 fly 方法来创建超级狗。
class SuperDog extends Dog {
constructor(name) {
super(name);
}
fly() {
return "Flying!";
}
}
让我们创造一只名叫“Daisy”的飞狗,让她吠叫飞翔!
|
|
我们可以访问 bark 方法,因为我们扩展了 Dog 类。 SuperDog 原型上 proto 的值指向 Dog.prototype 对象!
很清楚为什么它被称为原型链:当我们尝试访问对象上不直接可用的属性时,JavaScript 会递归地遍历 __proto__
指向的所有对象,直到找到该属性!
Object.create
Object.create 方法让我们可以创建一个新对象,我们可以将其原型的值显式传递给该对象。
const dog = {
bark() {
return `Woof!`;
}
};
const pet1 = Object.create(dog);
虽然 pet1 本身没有任何属性,但它确实可以访问其原型链__proto__
上的属性! 由于我们将 dog 对象作为 pet1 的原型prototype
传递,因此我们可以访问 bark 属性。
|
|
Perfect! Object.create 是一种让对象直接从其他对象继承属性的简单方法,通过指定新创建的对象的原型prototype
。 新对象可以通过沿着原型链__proto__
访问新属性。
优点
原型模式允许我们轻松地让对象访问和继承其他对象的属性。
由于原型链允许我们访问未直接定义在对象本身上的属性,我们可以避免方法和属性的重复,从而减少使用的内存量。
知识点
prototype
对象/类本身的属性__proto__
原型链上的属性- new 将类实例化为一个对象
- extends 类继承
- Object.create 创建一个新对象