首先写一个简单的类。
function Animal(nickName){ this.getNickName = function(){return nickName}; } Animal.prototype.canMiaomiao=false; Animal.prototype.eat=function(){console.log("animal eat");}; Animal.prototype.sleep=function(){console.log("animal sleep");};
上面实现了一个普通动物的类。nickName为其私有域,canSpeak为公有域。此类还有三个方法 getNickName, eat, sleep。
然后写一个子类。
function Cat(nickName, color) { this.superClass(nickName); this.getColor=function(){return color;}; } Cat.prototype=new Animal(); Cat.prototype.constructor=Cat; Cat.prototype.superClass=Animal; Cat.prototype.canMiaomiao=true; Cat.prototype.eat=function(){this.superClass.prototype.eat.call(this); console.log('cat eat');}; Cat.prototype.catchMouse=function(){console.log('catch mouse');};
Cat继承Animal,多了一个私有域color,多了新方法catchMouse,重写了方法eat,在eat中还调用了父类中的方法。运行下面代码,看发生了什么。
var a = new Animal('animal'); a.eat(); a.sleep(); a.getNickName(); var b = new Cat('cat','black'); b.eat(); b.catchMouse(); b.sleep(); b.getColor(); b.getNickName();
上面都是JS语法里面提供的方法。但这种方法只提供了单继承。如果想实现多继承,那需要引入新的方法mixin。在dojo中,mixin就是将一个object中的属性全部复制到另一个object。假设有两个父类A,B,现在需要设计一个子类,同时继承A和B,那么可以将A和B的属性全部mixin到C中,也可以C继承A后再minxin B。Dojo便使用了此方法实现多继承。
很多JS框架,都为了更好的结构化,模拟java似的面向对象。在java中,初始化一个类使用defineClass。dojo则设计了dojo.declare这一方法来声明一个类。下面的代码便定义了我们JS中的defineClass,虽然它只实现了单继承,但从中可见一斑。
// 传入参数为JSON, JSON中包含的properties如下。 // className: /*String*/ // extend: /*function*/ // constructor: /*function*/ // methods and fields: /*properties*/ // 下面代码不考虑容错性。 function defineClass(/*JSON*/data) { var className = data.className; var constructor = data.constructor || function(){}; var superClass = data.extend || Object; var proto = new superClass(); for (var property in data) { proto[property] = data[property]; } proto.constructor = constructor; proto.superClass = superClass; proto.className = className; constructor.prototype=proto; window[className] = constructor; }
有了以上这个简单的defineClass,我们可以换一种方式来动态的加载Animal和Cat类。
var AnimalClass = { className:'Animal', constructor: function(nickName){ this.getNickName = function(){return nickName}; }, extend:null, canMiaomiao:false, eat:function(){console.log("animal eat");}, sleep:function(){console.log("animal sleep");} }; defineClass(AnimalClass); var CatClass = { className:'Cat', constructor: function(nickName, color) { this.superClass(nickName); this.getColor=function(){return color;}; }, extend:Animal, canMiaomiao:true, eat:function(){this.superClass.prototype.eat.call(this); console.log('cat eat');}, catchMouse:function(){console.log('catch mouse');} }; defineClass(CatClass); var a = new Animal('animal'); var b = new Cat('cat');
以上只是简单的defineClass。Dojo的多继承比这要复杂很多,比如如何调用父类的方法。但是原理是非常相近的。这里就不再仔细分析了。如果有问题,请留言。