继承和原型链
原型链
JavaScript几乎所有东西都是object
JavaScript
中的每一个object
内都有一个prototype
属性,指向另外一个object
。另外一个object
又有它自己的prototype
,又指向一个,这就构成了原型链。
若果你一直跟着这条原型链走,你会发现最终的那个object
的prototype
是null
类继承的基础
当你请求一个属性的时候,如果这个object
没有包含,那么它会一直沿着这条原型链去查找,直到到达原型链的结尾。这种行为可以让我们实现类的创建与实现。
类继承的演示
动物类:
function Animal(name) {
// Instance properties can be set on each instance of the class
this.name = name;
}
// Prototype properties are shared across all instances of the class. However, they can still be overwritten on a per-instance basis with the `this` keyword.
Animal.prototype.speak = function() {
console.log("My name is " + this.name);
};
var animal = new Animal('Monty');
animal.speak(); // My name is Monty
我们创建一只猫来继承动物类:
function Cat(name) {
Animal.call(this, name);
}
Cat.prototype = new Animal();
var cat = new Cat('Monty');
cat.speak(); // My name is Monty
我们将Cat
的prototype
指向Animal
的一个实例,所以Cat
拥有Animal
的所有属性;同时我们使用Animal.call
来继承Animal
的构造器(有点像其他语言里的super()
)。
call()
是一个特殊的函数,可以让我们调用一个函数,并指定在那个函数中的this
的值
所以在Animal
构造器中,当this.name
被设置的时候,this
实际上是指的Cat
,是Cat
的name
属性被设置上了值,而不是Animal
的。如果通过浏览器的console
可以看到,Cat
有它自己的name
,我们看prototype
上的Animal
的name
是undefined
。当JavaScript
请求name
属性的时候,它在Cat
中找到了name
属性,便不在沿着原型链继续向上查找。然而,当我们请求cat.speak
的时候,JavaScript
依然要从原型链的Animal
中来找到这个方法。