最近在通过JavaScript设计模式研究js的继承.
但是作为java出身,由于java提供了语言级别的继承,对于js要使用其他手段来实现继承还是有比较多的障碍的,故写一篇博客来记录自己的一个学习心得.
我们都知道js使用原型链的方式来实现属性和方法的搜索,js本职上是不提供继承的,但是由于js的function对象的原型时暴露的,我们可以通过更改一个function对象的原型来达到继承的目的.
目前的继承比较多的有两种方式分别是类式继承和原型继承,但是目前先讨论类式继承,毕竟类式更符合类似于java语言提供的继承方式,废话不多说下面看代码:
/**
* 为所有的类添加一个继承的方法
* 用这个方法模拟继承
*/
Function.prototype.extends = function extend(superClass) {
if(!extend.F) {
extend.F = new Function();
}
extend.F.prototype = superClass.prototype;
this.prototype = new extend.F();
this.prototype.constructor = this;
this.prototype.super = superClass;
if(superClass.prototype.constructor == Object.prototype.constructor) {
superClass.prototype.constructor = superClass;
}
}
/**
* 定义父类
*/
var supClass = function(id) {
this.id = id;
}
supClass.prototype.getId = function() {
return this.id;
}
首先,我在函数对象的原型上定义了一个extends的方法,至于为什么定义这个方法是因为我希望在定义子类的时候使用类名.extends的方式去调用这个方法,这是个人的一个喜好吧!我觉得这样更符合面向对象的思想,我们可以看到在这个方法中我在其中添加了一个super,我相信使用过java的人都知道,在java中就含有同样的东西,但是这个不一样,这个super表示的父类的构造方法,因为在子类的构造方法中我们要使用call的形式调用这个方法并且传递子类对象作为调用者,这是一般的实现,但是我个人不是很喜欢这种实现方式,我觉得这种调用方式不是那么的面向对象,所以我将这个对象放入了子类的prototype对象中,这样我就可以在子类的构造方法中使用this.super的形式调用这个方法,从而实现对于父类构造方法中定义的公开方法和属性的继承,
下面是继承的实现代码:
/**
* 使用下面方法实现继承
*/
1 var subClass = (function() {
2 var __super__;
3 function Class(id) {
4<span style="white-space:pre"> </span><span style="font-family: Arial, Helvetica, sans-serif;">this.super = this.super || __super__;</span>
5 this.super(id);
6 __super__ = __super__ || this.super;
7 delete Class.prototype.super;
8 }
9 Class.extends(supClass);
10 Class.extends = undefined;
11 return Class;
12 })();
是不是觉得比较像Java中的继承啊,对于这个我使用了方法自执行,为什么要使用自执行呢?
因为在js的继承中我必须要使得在创建对象之前将父类绑定到子类的原型对象中,所以需要Class.extends这个方法执行在构建对象之前,处于目前水平有限,只能想到使用自执行来处理.
,忘了说了,我开始不是很明白在使用继承的时候为什么要使用一个空对象,我试图去掉那个空对象直接使用父类的对象,后来经过测试发现了其中的问题,就是我们通常会通过原型对象对一个类进行拓展,这时候我们会使得父类也被修改,不是我们所需要的.
从上面的代码可以看到,其中最核心的代码其实只有(1,3,5,8,9,11,12)7行,对于其他的只是我个人的习惯而已,我觉得不应该把想super这样的对象暴露给外面,而且extends这个方法也不应改暴露出去,但是目前没有找到方法怎么禁止在函数外面调用这个方法,无奈之下只有禁止通过当前类来调用这个方法,出此下策也是无奈之举,若有量测以后再改正.
综上为js模拟java继承之实现与思路