JavaScript与传统OO语言有所不同,那就是它并没有类的概念。因此,JavaScript中的对象也就和基于类的语言中的对象有所不同。那么,JavaScript中的对象是如何创建的,又是如何实现继承的呢?
一、首先说说创建对象。其实,创建对象有很多种方式。比如工厂方式、构造函数方式以及原型方式等等。而,在这里,我只想说说组合方式。
function Person( name, age, job ) {
this.name = name;
this.age = age;
this.job = job;
this.friends = ["Leo","Jack"];
}
Person.prototype = {
constructor : Person,
sayName = function(){
alert( this.name );
}
}
所谓组合,就是将构造函数和原型搭配使用来创建对象。构造函数负责实例属性,原型负责公有方法。这样既能够保证每个实例都有自己单独的一份属性值,又能得到公有的方法从而免去了重复创建方法造成的浪费。这是使用最广泛的方式,虽然逼格不高,但简单实用。
二、然后,我们再聊聊原型对象。先祭出一张无码大图:
很清晰:每个构造函数都会有一个prototype属性,它指向构造函数的原型对象;每个原型对象都有一个constructor属性,指回构造函数;创建出实例对象后,每个实例内部都会有一个prototype属性(记住是带双中括号的内部属性),指向原型对象。
理解了这张图,也有助于理解原型链的作用原理。
三、那么,撸点来了——原型链。
原型链这玩意是从哪扯出来的呢?嗯,是从继承。严谨起见,下面我还是用ECMAScript去代替JavaScript吧。ECMAScript感觉就像一个被阉割了的OO语言,没有类,而且不支持接口继承和实现继承。但又想行使男权,所以搞出了原型对象和原型链。
再祭出一张无码有水印大图:
发挥想象力,把上图想象成一条大铁链。连接点左边的原型对象是右边类型的实例,这样就形成了通路。例如想在左边的实例中寻找某个属性,结果没找到,那么就会去它的原型对象里面去找,还没找到,那又会跑到右边的原型对象里去找,直到追到Object对象,如果Object的原型对象上也没有,那就是真没有了...如此,便形成了一个原型链。