介绍
示例代码:
var Student = function(name){this.name = name;}
Student.prototype.speak = function(){console.log("Hello, I'm "+ this.name + ". ")}
var tom = new Student("Tom");
tom.speak();
tom.constructor === Student //true
Student.prototype.constructor === Student //true
tom.speak == Student.prototype.speak //true
tom.__proto__ === Student.prototype //true
//从上面的代码中得到启发,我们可以这样给Student.prototype添加方法:
tom.__proto__.sayHello = function(){console.log("Hello")};
//现在Student的任何一个对象都会有sayHello方法:
tom.sayHello();
结论: __proto__ 就相当于一个对象的原型,根据js调用规则,当一个对象调用一个方法时,如果对象本身不含有这个方法,就会从它的原型 __proto__ 中找,如果存在,直接调用;如果不存在,就会从 __proto__ 的 __proto__ 中找…
接下来看一个复杂一点的。
TypeScript中的extends 语法
在TypeScript中有 extends关键字,用来声明类的继承关系:
class Animal {
name: string;
speak(){console.log("Animal speak")}
}
class Dog extends Animal {
breed: string;
}
先看翻译成js之后的 Animal :
var Animal = (function () {
function Animal() {
}
Animal.prototype.speak = function () { console.log("Animal speak"); };
return Animal;
}());
从代码中可以看出 Animal 仅仅是一个普通的 function ;
下面是 Dog 的代码:
var Dog = (function (_super) {
__extends(Dog, _super);
function Dog() {
_super.apply(this, arguments);
}
return Dog;
}(Animal));
在定义 Dog 之前调用了 __extends 方法;同时 Dog 在构造时会调用 Animal 方法。
重点看看 __extends 的实现:
var __extends = (this && this.__extends) || function (d, b) {
//继承TypeScript中用static声明的方法,类似于js: Animal.func会继承到Dog.func
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
__extends 方法对 Dog 的 prototype 进行重新赋值,它是用'__'new出来的一个对象,它的 constructor 是 Dog
Dog.prototype.constructor === Dog //true
最后,来看看 Dog 对象是怎么调用 Animial 中的 speak 方法
var dog = new Dog();
dog.speak();
dog 本身并不含 speak 方法,于是runtime就会从 dog.__proto__(Dog.prototype) 中找, 也就是这个new 出来的'__'对象,它本身也不含有 speak 方法,接着又从它的 __proto__( __.prototype) 中找, 而 __.prototype 就是 Animal.prototype ,这里面就定义了 speak 方法,从而调用成功。
从上面的分析中可以知道,Animial.prototype 中的方法都被继承到 Dog 对象中了。