众所周知JS是没有类的概念的。其实只不过是没有Class这个关键字以及显式的类继承机制,我们完全可以通过把函数的原型当做类做到类继承。再进一步,更可以完全剥离类的概念,直接实现对象的继承。
这里有一个需要深究的概念,类是什么,继承是什么。继承与类的关系又是什么。
先来说说“类”是干什么用的。在强类型语言C#里,是有Class这个关键字的。“类”是其实例的模板。这个模板不是具体的实物,而是一种准则,依据这个准则便可以产出符合规范的实例。这就好比家具厂家做家具。高端大气上档次的厂家会有设计图,有数控机床3D打印机神马的,家具是从自动化生产线下来的成品。这里的设计图、机床指令、打印机的驱动代码等等就是“类”。那么我们只能利用类的机制才能制造符合规范的实例吗。想象一下,一个家具小作坊做家具。他们简单到没有图纸,只有一个祖师爷做出来的原型成品供着。工人师傅们通过观察这个原型仿造出一个个家具。这些家具和祖师爷的原型足够像以至于对于消费者使用来说没啥区别。也可以说这是在制造符合规范的实例。这便是JS里的原型机制。
继承是啥呢。类的继承简单来说就是家具厂对于其设计图的拷贝、再加工,称为子设计图。子设计图拥有原父设计图的一些特性,从而使用子设计图为规范生产出来的家具具有和父设计图家具
相似的特性。原型继承呢?想修改祖师爷的成品怎么办。那么先要按原型先做出来一个成品,再对这个成品加工,称为子成品。再拿这个子成品作为批量加工的原型制作家具就可以啦。
下面聊聊JS里的具体实现
1.类继承
1.1 父类的实例作为子类的原型(简单类继承模式)
function FatherClass(name) { this.name = name; } FatherClass.prototype.ShowName = function () { console.log(this.name); } function ChildClass(name) { this.name = name; } ChildClass.prototype = new FatherClass(); var child = new ChildClass("child"); child.ShowName(); //child
缺点是无法给通过子类给父类的构造函数传递参数
1.2 父类的实例作为子类的原型 并在子类的构造函数里借用调用父类的构造函数 call apply (传统经典类继承模式)
缺点是1.4会提到
1.3 父类的原型作为子类的原型
缺点是子类保存了父类的原型引用 无法避免通过子类修改父类的原型 从而影响父类的实例
1.4 父类的原型作为临时类的原型 再把临时类的实例赋给子类的原型
避免了子类对于父类原型的引用,无法修改父类的原型了,子类原型的修改只会体现在临时类的那个实例上。
相比1.1、 1.2的好处是理念上的,即类的继承应该与对象无关,相反1.1和1.2都是通过实例化一个父类的对象链接起来的。
2.对象继承
2.1 父对象作为临时类的原型 实例化的临时类作为子对象作为返回(ECMAScript5里面的Object.create()函数是对这个机制的实现)
2.2 复制父对象的属性 浅复制(firebug extend) 深复制(jquery extend(), YUI3 clone())
浙公网安备 33010602011771号