类
JavaScript 的原型系统可以解释为对一种面向对象的概念(称为类(class))的某种非正式实现。 类定义了对象的类型的形状 - 它具有什么方法和属性。 这样的对象被称为类的实例(instance)。
原型对于属性来说很实用。一个类的所有实例共享相同的属性值,例如方法。 每个实例上的不同属性,比如我们的兔子的type
属性,需要直接存储在对象本身中。
所以为了创建一个给定类的实例,你必须使对象从正确的原型派生,但是你也必须确保,它本身具有这个类的实例应该具有的属性。 这是构造器(constructor)函数的作用。
function makeRabbit(type) {
let rabbit = Object.create(protoRabbit);
rabbit.type = type;
return rabbit;
}
JavaScript 提供了一种方法,来使得更容易定义这种类型的功能。 如果将关键字new
放在函数调用之前,则该函数将被视为构造器。 这意味着具有正确原型的对象会自动创建,绑定到函数中的this
,并在函数结束时返回。
构造对象时使用的原型对象,可以通过构造器的prototype
属性来查找。
function Rabbit(type) {
this.type = type;
}
Rabbit.prototype.speak = function(line) {
console.log(`The ${this.type} rabbit says '${line}'`);
};
let weirdRabbit = new Rabbit("weird");
构造器(实际上是所有函数)都会自动获得一个名为prototype
的属性,默认情况下它包含一个普通的,来自Object.prototype
的空对象。 如果需要,可以用新对象覆盖它。 或者,你可以将属性添加到现有对象,如示例所示。
按照惯例,构造器的名字是大写的,这样它们可以很容易地与其他函数区分开来。
重要的是,理解原型与构造器关联的方式(通过其prototype
属性),与对象拥有原型(可以通过Object.getPrototypeOf
查找)的方式之间的区别。 构造器的实际原型是Function.prototype
,因为构造器是函数。 它的prototype
属性拥有原型,用于通过它创建的实例。
console.log(Object.getPrototypeOf(Rabbit) ==
Function.prototype);
// → true
console.log(Object.getPrototypeOf(weirdRabbit) ==
Rabbit.prototype);
// → true