js继承探讨
每当我们说到js的继承时,在您的脑袋的第一反应就是prototype原型机制来实现。但是您是否使用过其他的方法来实现继承呢,或者您是否了解其他实现方式及各种不同的继承实现机制的优缺点呢?
好了,下面我们就来看看几种比较常见的继承实现吧。
1、 prototype方式
这种方式最为简单,只需要让一个类的prototype为被继承的一个实例就ok,然后直接使用BaseClass的方法。
prototype属性是啥意思呢?prototype即为原型,每一个对象(由function 定义出来)都有一个默认的原型属性,该属性是个对象类型。并且该默认属性用来实现链的向上攀查。意思就是说,如果某个对象的属性不存在,那个将通过prototype属性对应的对象的来查找该对象的属性。如果prototype查找不到呢? js会自动地找prototype的prototype属性对应的对象来查找,这样就通过prototype一直往上索引攀查,直到查找到了该属性或者prototype最后为空("undefined");
例如:上例中的instance.ToString()方法。js会先在instance实例中查找是否有ToString()方法,因为没有,所以查找Derived.prototype属性,而prototype 为 NewClass的一个实例,该实例有ToString()方法,于是调用成功;同样给instance 的 name 属性赋值时也是查找prototype来实现的。
注意,每一个对象得prototype都默认对应一个object对象,但是该对象不等于Object;如何验证呢?看如下代码:result 所得值为 false;
这段代码的
以下几个需要注意:
2、apply方式
在这种方式下,我们最需要理解的就是apply函数的作用。
该方法普遍的解释为用A方法去替换B方法。第一个参数为B方法的对象本身,第二个参数为一个数组,该数组内的值集合为需要传递给A方法对应的参数列表,如果参数为空,即没有参数传递,则通过 new Array() 来传递,null无效。
一般的方式为:
但是在本例当中,apply方法执行了两步操作。
第一:将BaseClass以apply传递的Array数组作为初始化参数进行实例化。
第二:将新生成的实例对象的所有属性(name,age,ToString方法)复制到 instance实例对象。这样就实现了继承。
3、call+prototype 方式
其实,call函数和apply方式有很类似的作用,都是用A方法去替换B方法,但是参数传递不一样,call方法的第一个参数为B方法的对象本身,和面的参数列不用Array对象包装,直接依次传递就可以。
为什么作用类似,call方式的实现机制却要多一条 Derived.prototype = new BaseClass(); 语句呢?那是因为call方法只实现了方法的替换而没有作对象属性的复制操作。
call方法实际上是做了如下几个操作:
例:
this.fooB.call(this,"sorry")执行了如下几个操作:google Map API 的继承就是使用这种方式。大家可以下载的参考参考(maps.google.com)。