`
Mootools
  • 浏览: 45009 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

锁定老贴子 主题:

阅读更多
我为什么选择mootools,抛弃了prototype. (mootools 与 prototype 核心代码分析)


===========================================
前言
===========================================

最近喜欢上了mootools(相见恨晚啊),在公开表示了对他的偏爱.
很多朋友都问我为什么要移情别恋,其实理由还是蛮多的.

今天在这里打算列举出一部分.让更多的朋友能够了解一下mootools,也希望有更多的朋友喜欢上他.


文章的标题注定了我会更多的讲述 mootools比prototype好的地方,
希望大家不要被我的误导,以为mootools处处都比prototype好.
mootools还是有一些不足的.


本次对比针对 mootools 1.11版 和 prototype 1.51版,
只比较了一些核心代码,其他的工具方法,辅助函数不再本文讨论之内.


开始前,再次重申一遍:我曾经很爱prototype,而且我将永远都会用"伟大"来形容它.


好 下面对比正式开始 (
mootools以下简称moo.
本文所引用的代码, 只是起到说明作用,不保证他们都可以被正确的执行.
同时为了使本文简洁一些,引入的 一些 moo和prototype的代码也只是片段或是伪代码.
)

===========================================
一. 类机制
===========================================


js里的类实际上就是function.
如果不使用任何框架和组件,那么想创建一个自己类也不是难事,方法如下:


Java代码
1.var PersonClass=function(name,gender){  
2.    this.name=name;  
3.    this.gender=gender;  
4.    alert("My name is "+this.name);  
5.}  
6. 
7.var myGirlFriend=new PersonClass('Vickey','female'); 
var PersonClass=function(name,gender){
this.name=name;
this.gender=gender;
alert("My name is "+this.name);
}

var myGirlFriend=new PersonClass('Vickey','female');



执行 后, 会创建一个PersonClass类的实例myGirlFriend, 并执行function内的语句.
那些语句可以理解为是类的构造函数.



Prototype
现在来看看在prototype的帮助下如何去定义这个类:

Java代码
1.var PersonClass = Class.create();  
2. 
3.PersonClass.prototype.initialize=function(name,gender){  
4.    this.name=name;  
5.    this.gender=gender;  
6.    alert("My name is "+this.name);  
7.};  
8. 
9.var myGirlFriend=new PersonClass('Vickey','female');  
10. 
11.//如果想给类增加属性和方法时使用   
12.PersonClass.prototype.XXX=...;  
13.//或者是使用 prototype提供的   
14.Object.extend(PersonClass.prototype, {...} ); 
var PersonClass = Class.create();

PersonClass.prototype.initialize=function(name,gender){
this.name=name;
this.gender=gender;
alert("My name is "+this.name);
};

var myGirlFriend=new PersonClass('Vickey','female');

//如果想给类增加属性和方法时使用
PersonClass.prototype.XXX=...;
//或者是使用 prototype提供的
Object.extend(PersonClass.prototype, {...} );


(关于Object.extend稍后在对比继承机制时再细说.)


再来看看prototype是实现类机制的核心代码.

Java代码
1.var Class = {  
2.  create: function() {  
3.    return function() {  
4.      this.initialize.apply(this, arguments);  
5.    }  
6.  }  
7.} 
var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}


通过看代码不难看出,prototype的Class实际上只是帮助我们抽象出了"类的构造函数".
而当我们在prototype的这种机制下进行类的定义时,实际上带来的好处是非常有限的.
prototype的Class只是从结构对我们的类进行了重新规划. 而这样的规划意义并不是很大.
而且prototype带有强制性,即, initialize 是必须要定义的.
实际上这里存在一个缺陷, Class应该提供一个默认的initialize(一个空函数就好),
或者是在create返回的function里进行必要的判断.
(prototype1.6的类机制变化比较大,但是还没仔细研究过,所以不敢轻易评论).


Mootools

现在来看看在 moo的帮助下如何去定义一个类:

Java代码
1.var PersonClass = new Class( {  
2.    initialize: function(name,gender){  
3.        this.name=name;  
4.        this.gender=gender;  
5.        alert("My name is "+this.name);  
6.    }  
7.});  
8.var myGirlFriend=new PersonClass('Vickey','female'); 
var PersonClass = new Class( {
initialize: function(name,gender){
this.name=name;
this.gender=gender;
alert("My name is "+this.name);
}
});
var myGirlFriend=new PersonClass('Vickey','female');

其中类的 initialize 不是必须的.
如果你想给 PersonClass 增加属性和方法,你可以在new Class的参数里直接以 json方式定义.
也可以使用 如下方式

Java代码
1.PersonClass.implement ({   
2.    age:0 ,  
3.    getName : function() {return this.name;}  
4.} , {...}, ..... ); 
PersonClass.implement ({
age:0 ,
getName : function() {return this.name;}
} , {...}, ..... );

implement支持多个{}.关于implement稍后在对比继承机制时再细说.


在来看一下moo类机制的一些核心代码.


Java代码
1.var Class = function(properties){  
2.    var klass = function(){  
3.        return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;  
4.    };  
5.    $extend(klass, this);  
6.    klass.prototype = properties;  
7.    klass.constructor = Class;  
8.    return klass;  
9.};  
10. 
11.Class.prototype = {  
12.    extend: function(properties){  
13.        var proto = new this(null);  
14.        for (var property in properties){  
15.            var pp = proto[property];  
16.            proto[property] = Class.Merge(pp, properties[property]);  
17.        }  
18.        return new Class(proto);  
19.    },  
20.    implement: function(){  
21.        for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]);  
22.    }  
23. 
24.}; 
var Class = function(properties){
var klass = function(){
return (arguments[0] !== null && this.initialize && $type(this.initialize) == 'function') ? this.initialize.apply(this, arguments) : this;
};
$extend(klass, this);
klass.prototype = properties;
klass.constructor = Class;
return klass;
};

Class.prototype = {
extend: function(properties){
var proto = new this(null);
for (var property in properties){
var pp = proto[property];
proto[property] = Class.Merge(pp, properties[property]);
}
return new Class(proto);
},
implement: function(){
for (var i = 0, l = arguments.length; i < l; i++) $extend(this.prototype, arguments[i]);
}

};



代码的具体原理就不细说了.大家在moo的Class里看到了 extend 和implement,那下面就来具体说一说moo和prototype的 继承机制吧.


===========================================
二. 继承机制
===========================================

Prototype
prototype提供的继承很简单.

Java代码
1.Object.extend = function(destination, source) {  
2.  for (var property in source) {  
3.    destination[property] = source[property];  
4.  }  
5.  return destination;  
6.} 
Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}


他只是把source里的属性赋给destination,同时会覆盖destination里的同名属性.
他可以用于对象,也可以用于类,当要实现类的继承时,destination要使用 MySubClass.prototype.

prototype的继承机制可以说是非常薄弱的.


Mootools

moo提供了三种继承机制:

首先他也提供了简单的继承机制:
Objcet.extend (注意,不是上面代码中 Class 里的 extend)
他的代码如下

Java代码
1. 
2.var $extend = function(){  
3.    var args = arguments;  
4.    if (!args[1]) args = [this, args[0]];  
5.    for (var property in args[1]) args[0][property] = args[1][property];  
6.    return args[0];  
7.};  
8.Object.extend = $extend; 

var $extend = function(){
var args = arguments;
if (!args[1]) args = [this, args[0]];
for (var property in args[1]) args[0][property] = args[1][property];
return args[0];
};
Object.extend = $extend;

他的使用方法和 prototype 完全一样.

但是大家可能注意到了 这句 if (!args[1]) args = [this, args[0]]; 这句的纯在使得下面的代码写法成为可能.

Java代码
1.var myObjcet={....};  
2.myObjcet.extend=$extend;  
3.myObjcet.extend(objA);  
4.myObjcet.extend(objB);  
5.myObjcet.extend(objC); 
var myObjcet={....};
myObjcet.extend=$extend;
myObjcet.extend(objA);
myObjcet.extend(objB);
myObjcet.extend(objC);


简单的一句话,让extend的用法增加了更多的灵活性,不得不赞一个了!!!

下面说说重点, moo的类里的extend和 implement
先说 implement,之前已经说了一些了


Java代码
1.var MyClassA = new Class();  
2.MyClassA.implement( { methodA : function() {... } }  ); 
var MyClassA = new Class();
MyClassA.implement( { methodA : function() {... } }  );


执行后 MyClassA 将拥有 methodA.

implement用来向类中添加属性和方法(会覆盖同名属性和方法),相当于
Object.extend (MyClassA.prototype , {... } )
但是Object.extend 不支持多个source,implement可以,示例如下:
MyClassA.implement( objA , objB, objC ... );


下面来看看moo的Class.extend.
moo的Class.extend才是我们期待的真正的"类继承",看一下官方的示例


Java代码
1.var Animal = new Class({  
2.    initialize: function(age){  
3.        this.age = age;  
4.    }  
5.});  
6.var Cat = Animal.extend({  
7.    initialize: function(name, age){  
8.        this.parent(age); //will call the previous initialize;  
9.        this.name = name;  
10.    }  
11.}); 

var Animal = new Class({
initialize: function(age){
this.age = age;
}
});
var Cat = Animal.extend({
initialize: function(name, age){
this.parent(age); //will call the previous initialize;
this.name = name;
}
});



看那个parent() !!!!
通过moo的Class.extend实现的继承提供一个关键的方法 parent().
使用他你可以调用父类中的同名方法,好像java里的super一样.
这个示例已经可以说明一切了.


关于prototype和moo的类机制和继承机制的对比就到这里,孰优孰劣大家心里应该有数了吧.

===========================================
三.抽象对象
===========================================


再来看一看"抽象对象". 这个虽然对于开发人员来说用处不大,但还是对比一下吧,小细节也能看出作者的用心.

Prototype
prototype的抽象对象很简单
var Abstract = new Object();
具体的意义不大.


Mootools
moo的的抽象对象相对更完善一些.

Java代码
1.var Abstract = function(obj){  
2.    obj = obj || {};  
3.    obj.extend = $extend;  
4.    return obj;  
5.}; 
var Abstract = function(obj){
obj = obj || {};
obj.extend = $extend;
return obj;
};

支持自定义抽象(以参数形式传入),同时会为抽象对象自动添加extend方法.


===========================================
四. 关于 $()
===========================================

Prototype
prototype的$大家都比较熟悉了, 工作原理就是
通过id取得一个页面元素(或者直接传入一个页面元素对象),然后给他增加一些prototype提供的方法和属性,来方便开发人员对页面元素的使用.


Mootools
moo在这方面做的差不多.
不同的主要有两点, 首先moo为页面元素增加的方法和属性与prototype的不同(这个稍后会介绍),另外一个不同是moo的$兼具了对象管理的一个功能.
他引入了一个  Garbage 类, 来对页面元素进行一个统一的管理和回收(主要是回收).
可以更好的减少js(或浏览器)造成的内存泄露等问题.

具体的大家可以看一下代码,在这里就不详细说明了.


===========================================
五.关于 Array Enumerable Hash
===========================================


prototype 和 moo 都提供了集合迭代方法 (each)
这个网上已经有一篇不错的对比文章,我就不在这里重复了
http://blog.fackweb.cn/?p=50.


moo的 forEach/each方法: function(fn, bind){..}
那个bind 结合代码 和 上面那篇文章, 大家应该可以很好的看出来prototype和moo的不同与优劣.


prototype里面有 Enumerable 的概念,moo没有.
但是我个人一直觉得 Enumerable 比较鸡肋.
在实际开发中,很少使用.
Enumerable的功能完全可以 用普通json对象 或者是 Hash来实现.
moo的作者也许同样这么认为.所以 不再 设置一个 鸡肋的 Enumerable类.
但是请大家放心, Enumerable 能做的事情, 在moo里也能完成.

可以理解为

moo的 Array +  Hash +{} 完全可以接替 prototype的 Array + Enumerable + Hash +{}
当然对于一些工具方法两者提供的都不太一样,不好比较,但是那些方法都是附属品.
我们完全可以自己来实现,所以不在这次的比较范畴之内.


===========================================
六. 关于 Element
===========================================

两者的 Element 从作用上看类似.都是一种对页面元素的包装,为页面元素添加了一些诸如 addEvent remove style之类的方法.
但是大家通过看代码可以发现 moo的实现明显更简洁 更OO.

同时还有一个关键的不同,prototype又提取出了一个Form对象,里面包含了很多表单相关的方法.
同时还衍生出了 serializeElements Method 等等很多类和方法,代码瞬间变得异常复杂和难以琢磨.


而moo中没有Form对象,在moo中,Form本身就是一个Element 他没什么特别的,这样的思想类似components模式
普通Element具备的方法 Form 都应该具备, Form具备的方法 Element也都应该包含.form 和 其他页面元素没什么不同.
form元素只是一个包含了 input select textarea等子元素,同时拥有action target等属性而已.
一个div 一个span 一个td... 同样可以包含input select textarea子元素,同样可以拥有.action target属性.
浏览器处理他们的方式可能不同,但是在moo面前,大家完全平等.


其实prototype里 form和普通页面元素几乎也是平等的,但是问题就是,既然是平等的,又何必硬生生的造出Form以及那么多的衍生物呢?



===========================================
七.Ajax
===========================================

Prototype
prototype的ajax实现主要是靠一个 Ajax类 来实现.(但是这个类形同虚设,大家更多的是和 Ajax.Request 类打交道.


先来看一个prototype下一个简单的ajax提交实例:

Java代码
1.var myAjax = new Ajax.Request( url,{parameters: myData , onComplete: callBackFunction } ); 
var myAjax = new Ajax.Request( url,{parameters: myData , onComplete: callBackFunction } );

其中 myData 可以是字符 : "name=Vickey&gender=female";
也可以是对象 { name : Vickey, gender : female }


Mootools
moo首先在将ajax机制分层.提取出了一个基类:XHR.
目前XHR有两个子类, 一个是 Ajax ,另一个是Json.Remote.

在moo下一个简单的ajax提交实例:

Java代码
1.var myAjax =new Ajax(url, {data : myData , onComplete: callBackFunction  }).request(); 
var myAjax =new Ajax(url, {data : myData , onComplete: callBackFunction  }).request();

大家可以看到request成为了Ajax对象的一个方法,这样的设计显然是更合理更自然 也更OO的.

而且关键的一点是,你可以提前创建好你需要的ajax对象.在需要发出请求时再发出请求.


Java代码
1.var myAjax =new Ajax(...);  
2.....  
3.myAjax.request(); 
var myAjax =new Ajax(...);
.....
myAjax.request();

同时还有一个重要特性, request是支持参数的,这个参数就是你要提交的数据.

也就是说,你可以在new Ajax时不指定数据或者指定一个默认数据.
在提交的时候可以提交另一个data.如.

myAjax.request(yourData);

其中data可以是字符串,可以是对象, 也可以是一个页面元素.

要用ajax提交一个form 或者一个 div下的所有表单元素,只是改变一下 myData.
var myData= $("formID");  // var myData= $("divID");
然后就和普通的ajax提交完全一样了.

myAjax.request(myData);

当然还有更oo的方式 :
myData.send({onComplete: callBackFunction });

用后一种方式的时候要保证提交的元素有action属性,没有你就赋一个 myData.action=url.
prototype里如何实现这一功能呢??


Prototype
Form.request($("formID") ,{ onComplete: callBackFunction });

当然prototype里也可以类似moo的做法 , 只要让myData=$("formID").serialize(true) 就可以了.
但是这一个小小的不同,反映出了设计上的差距.


Mootools
moo的Json.Remote类,简单,但是很实用:


Java代码
1.var jSonRemoteRequest = new Json.Remote( url , {onComplete:callBackFunction }).send({name: 'Vickey',gender: 'female' }); 
var jSonRemoteRequest = new Json.Remote( url , {onComplete:callBackFunction }).send({name: 'Vickey',gender: 'female' });

这个类和Ajax类的本质区别是,
他提交的是一个序列化后的 json字符串("{name: 'Vickey',gender: 'female' } "),而不是把 json对象转化成QueryString ("name=Vickey&gender=female");



===========================================
结束语
===========================================

写这篇文章不是要批评prototype,以我现在的水平还没那个资格.
只是和mootools对比后, prototype在设计上的不足立刻就显现了出来.

虽然prototype新版本变化很多,很多我上面提到的一些不足都改正了,而且也加入了很多以前不具备的新的特性.
但是prototype现在的发展停留在:"修补不足,增加功能"的阶段,而没有从设计上进行深层次的重构,所以我不认为他在mootools面前有足够的底气.

至于jquery我没有深入研究过,但是它的设计觉得完全是prototype风格的, 注意,我说的是设计风格,而不是代码风格.
代码上他可能写的更精妙,更有趣,但是设计上依然是prototype风格:薄弱的类机制,靠简单的extend支撑起整个系统.
JQuery在很多方面很出色,但是归根结底他和prototype走在一条路上,只是在有些方面他走的更快.


mootools并非完美无缺,但是至少现在他美的地方比prototype更多,缺的地方比prototype更少.

所以,我选择mootools. 你呢??

不要听评论,不要看介绍, 只要看看他们的源代码, 同时动手用他们写些东西, 你的答案自然会浮现出来.

分享到:
评论

相关推荐

    编程项目+ASP.NET&SQL2008+BBS在线论坛+毕业项目实战

    帖子管理:管理员可以管理帖子,包括编辑、删除不当内容或锁定不活跃的讨论。 用户权限管理:系统可以设置不同的用户权限,如普通用户、版主和管理员。 搜索功能:用户可以搜索论坛中的帖子和用户。 用户个人资料...

    SPB 2.0 Plus(急速先锋论坛Plus版) III build 4.3.15

    版主的功能包括:屏蔽帖子内容,删除帖子,移动帖子,冻结帖子(被冻结的帖子不允许回复),锁定帖子(被锁定的帖子普通用户无权浏览),精华帖子,帖子置顶,冻结论坛栏目,锁定论坛栏目。管理员功能:论坛板块,...

    SpeedPioneer(速度先锋) Plus 4.2.27

    版主的功能包括:屏蔽帖子内容,删除帖子,移动帖子,冻结帖子(被冻结的帖子不允许回复),锁定帖子(被锁定的帖子普通用户无权浏览),精华帖子,帖子置顶,冻结论坛栏目,锁定论坛栏目。管理员功能:论坛板块,...

    LeadBBS v2.10 论坛.rar

    104.允许定义显示帖子主题的长度(版面中),自动判断此帖所占宽,不产生换行保持美观和空间最小占用 105.支持显示主题帖子的页数,点击可进入最后回复页面 106.允许设定Session和cookie名,以防同网站cookie相互替换...

    SpeedPioneer(速度先锋) 1.0 3101

    超级用户功能设置: 版主的功能包括:对管辖的版面具有屏蔽帖子内容,删除帖子,移动帖子,冻结帖子(被冻结的 帖子不允许回复),锁定帖子(被锁定的帖子普通用户无权浏览),精华帖子,帖子置顶的权限。...

    pxljm:pixel jam 2011 参赛作品 - 锁定帖子竞赛以确保历史准确性

    为 pxljm 2011 编写的游戏; pxljm 是一个 48 小时的游戏制作比赛,所有代码和资产必须... 这是一款以太空为主题的资源获取与控制游戏。 我们没有美工,所以你可以得到我们辉煌的程序员艺术:三角形的船和圆形的行星!

    nodebb-plugin-archiver:适用于NodeBB的Archiver插件,因此,经过一定天数后的帖子将被自动锁定

    NodeBB主题存档器此插件可用于自动锁定已存在一定天数的主题。安装npm install nodebb-plugin-archiver 然后启用插件并从管理面板配置其设置。

    中国软件网论坛 v1.9.0 license date

    让你一目了然当天帖数,20,会员列表增加搜索功能,21,增加快速回复帖子功能,22,首页显示/隐藏版主功能,23,修复不能锁定帖子功能,24,增加转移帖子功能,25,修改了即时更新帖子,用户,积分问题,26,所有分页更改为数字导航...

    SpringMVC论坛演示系统Forum_J2EE

    (4) 论坛 主题帖子和回复帖子的CRUD操作。 二、使用技术:(1) Spring+SpringMVC+Hibernate整合框架;(2) HibernateTemplate模板;(3) DIV+CSS、HTML5、jquery;(4) JSTL、JSP tagment、分页组件; (5) Tomcat + MySQL...

    中国软件网论坛程序 v1.9.0

    23,修复不能锁定帖子功能, 24,增加转移帖子功能, 25,修改了即时更新帖子,用户,积分问题, 26,所有分页更改为数字导航式分页,比较方便, 27,增加拥护ip锁定功能, 后台管理帐号和密码:i263.net

    refire论坛:使用React,Redux和Firebase构建的无服务器论坛

    换届论坛使用和由React,Redux...锁定/解锁线程) CSS-in-JS样式的组件,完全主题化深色和浅色主题修改单个帖子用户可以编辑自己的帖子路线图允许将板和线程正确添加为书签使用redux-search搜索图片附件上传到Firebase

    社论:《 Ghost》的免费开源主题

    这是社论版,一种面向新闻的设计,基于动态“锁定”侧边栏(请尝试将其切换为实际操作!)构建,并且专门用于以内容为中心的网站。 最初由为创建,后来移植到 演示: : 第一次使用Ghost主题? Ghost使用一种称为...

    Advisory-editorial:AdvisorySG的修改的编辑主题

    社论这是社论版,一种面向新闻的设计,基于动态“锁定”侧边栏(请尝试将其切换为实际操作!)构建,并且专门用于以内容为中心的网站。 最初由为创建,后来移植到 演示: :第一次使用Ghost主题? Ghost使用一种称为...

    论坛:使用Express,Vue和Sequelize创建的论坛软件

    锁定或删除主题和帖子 封锁使用者IP位址 暂停用户创建帖子或启动主题 屏幕截图 主页 管理控制台 管理员设置页面 管理员用户页面 管理员审核页面 安装 要在Heroku上安装: git clone https://github.com/sbkwgh

    仿动网的jsp论坛

    2.贴子管理:可以在自己管辖的论坛内进行贴子删除、锁定、解除锁定、转移论坛、批量删除某用户贴子等 2).管理员功能:必须登陆管理页面 论坛管理: 1.论坛管理:可以对所有论坛进行增加、修改、删除、...

    一个ASP论坛:小清论坛源码 v2.0.rar

     6、后台可以开启帖子审核模式,开启后,会员发贴全部都需要审核才可以正常显示。  7、会员密码采用32位MD5加密方式,只能单向编译,防止会员信息泄露。  小清ASP论坛管理员登录帐号:  后台路径:/admin  后台...

    深博贴吧(仿百度)双数据库版 v2.0

    6、增加主题帖子移动功能,可将相应的主题帖子转移到其他贴吧,只有版主可操作 7、后台增加更新系统资料,有时一些删除或者移动贴吧的操作可能会导致总贴吧数、主题数及回复数不正常,这时只要进后台更新一下即可 ...

    LvBBS 94KK美化加强版

    帖子固顶,区固顶,总固顶,设定精华,锁定等功能 043.数据库在线压缩,备份功能 044.后台执行Sql语句 045.帖子设定已解决,技术论坛较适用 046.各种等级用户分类图标显示 047.精华区(分为本版...

    Raph:在帖子内容中呈现短代码的 WordPress 插件

    此外,由主题或插件添加的短代码将您锁定在这些产品中,因为如果您更改主题或卸载添加短代码的插件,您的内容将在不丢失的情况下被搞砸。 你有没有想过摆脱一个插件,但不能因为短路? 现在你可以。 这个怎么运作 ...

    中国软件网论坛程序 v1.9.0 License Date

    让你一目了然当天帖数, 20,会员列表增加搜索功能, 21,增加快速回复帖子功能, 22,首页显示/隐藏版主功能, 23,修复不能锁定帖子功能, 24,增加转移帖子功能, 25,修改了即时更新帖子,用户,积分问题, 26,所有分页更改为...

Global site tag (gtag.js) - Google Analytics