为什么 jQuery 的理念更好
这个博客上已经有很多帖子关于 jQuery 和 Prototype 之间代码大小的差异。这些帖子(我同意)的基本前提是,由于 jQuery 代码的结构方式,与 Prototype 相比,框架中所有典型的 Javascript 设计模式都变得更短更简单。
很长一段时间,我都是一个公开承认的 Prototype 迷。我在开始做 Rails 工作时发现了这个框架,对于 Rails 开发者来说,几乎没有其他选择。Prototype,尽管它很丑陋,却被烘焙到 Rails 中,而且很难放弃通过手工编写 Javascript 代码而获得的 Rails 带来的生产力提升。更进一步说,这就是我开始着手开发 jQuery on Rails 的原因,该项目旨在允许 Rails 开发者使用 jQuery 作为 Prototype 的直接替代品。
但回到这篇文章的目的,jQuery 的编程理念与 Prototype 有着更加根本的差异,不仅仅是代码大小。事实上,这种理念上的差异与 Java 和 Ruby 之间的差异非常相似,因此,Rails 社区完全接受 Prototype 是非常讽刺的。
让我们看一些代码比较。首先,在某个节点之后添加一些任意的 HTML。
在 Prototype 中
new Insertion.After('myId', 'Arbitrary HTML');
在 jQuery 中
$('#myId').after('Arbitrary HTML');
现在,我们还没有在减少代码混乱方面做太多工作(尽管 jQuery 的代码更干净),但是 Prototype 和 jQuery 每个解决问题的方式存在着根本的差异。
Prototype 创建了一系列单一的类,每个类封装了一些功能。然后,开发者传入一个 id 和一些其他参数,该类就会执行它应该做的事情。非常类似于 Java 封装功能的方式(例如 Math 类)。注意:这并不是说 Java 不能以这种方式做事。
jQuery 采用了一种截然不同的方式来解决这个问题。它将一组 HTML 节点视为要向其传递消息的对象(更类似于传统的 Ruby 方式)。因此,与其拥有一个单独的类在 HTML 节点之后添加文本,jQuery 将功能粘贴到 jQuery 对象上,该对象是由 $ 函数返回的。相比之下,Prototype 的 $ 函数返回的是一个普通的 DOM 节点。
Prototype 试图通过在框架的最新 RC 中添加的 $$ 方法来实现类似的功能,但存在根本差异。虽然 Prototype 的 $$ 返回的是 DOM 元素数组,而 jQuery 的 $ 是整个框架的根本基础。几乎所有 jQuery 函数都绑定到 jQuery 对象,该对象是由 $ 方法返回的。
jQuery 方式的优势非常明显
- 链式调用。由于 jQuery 对象上粘贴了功能,因此它们会返回其他 jQuery 对象,开发者可以随后向其传递其他消息。jQuery 网站上的一个简单示例是$(“p.surprise”).addClass(“ohmy”).show(“slow”);
- 使用 CSS 选择器和 XPath 运算符。由于 jQuery 向对象传递消息,因此它可以(并且已经)在 $ 方法中实现额外的选择器功能。粘贴到 jQuery 对象上的方法只看到一个包含一系列 DOM 元素的类似数组的对象。它不在乎我们如何获取它们。因此,插件开发者可以很容易地在 $ 方法中添加额外的解析器,或者将额外的函数粘贴到 jQuery 对象上。
- 这让我们想到了插件开发。jQuery 方式非常有利于插件开发。添加利用 jQuery 对象的功能非常容易,而且 jQuery 插件通常比它们的对应插件短很多。jQuery 插件
- 自动循环。jQuery 方法需要自动遍历数组中的所有 DOM 元素,并应用所需的方法。因此,$(expression).after(‘some HTML’) 会透明地将 HTML 添加到表达式返回的每个元素之后。例如,$(‘p’).after(‘some HTML’) 会将 ‘some HTML’ 添加到页面上的每个 <p> 之后。就我个人而言,我认为在我的代码中消除迭代(在大多数情况下)是使用 jQuery 的最实际、最日常的优势之一。
- 建立在自身之上。随着 jQuery 的成熟,在现有架构之上构建插件变得更加容易。由于所有 jQuery 函数都会自动循环,因此使用现有的 jQuery 函数意味着恼人的迭代几乎消失了。
还有更多,但贯穿所有优势的主线来自于 John Resig 精心设计的方式,即让 jQuery 对象/数组接受传递的消息,而不是构建各种单一的函数块,每个函数块都必须从头开始构建。
一些其他示例
Prototype 中的 AJAX 更新器
new Ajax.Updater('placeholder', url, { method: 'get', parameters: par });
jQuery 中的 AJAX 更新器
$('#placeholder').load(url + par);
注意:此示例不涉及如果我们想将响应加载到每个 <p> 对象中,我们会获得的明显迭代优势。
在 Prototype 中向元素添加类
Element.addClassName('element', 'className');
在 jQuery 中向元素添加类
$('#element').addClass('className');
在 Prototype 中向一组元素添加类
$$('.element').each(function(node) { Element.addClassName(node, 'className'); }
在 jQuery 中向一组元素添加类
$('.element').addClass('className');
最后一个示例最清楚地说明了方法论的差异。由于 jQuery 向 jQuery 对象传递消息,因此代码几乎没有改变。jQuery 不在乎我们现在是向一组对象还是一个对象添加类;底层代码是相同的(将类添加到对象中的元素集)。另一方面,Prototype 需要一个迭代器。
随着代码变得越来越复杂,jQuery 的扩展性很好,而嵌套循环在 Prototype 等框架中变得司空见惯。
[更新]一位敏锐的读者(Mislav)指出,Prototype 确实做了一些 jQuery 做的事情。Prototype 似乎将 Element 类绑定到 DOM 元素,允许像 $(‘myElement’).hide() 这样的操作。但是,它只适用于 Element 模块,并且似乎只适用于单个 DOM 元素。绑定 Elements 模块很酷,但这更像是一种事后诸葛亮,而不是 jQuery 将其作为基本设计决策的方式。
一个重要的更正:Prototype 很久以前就不再仅仅从 $ 函数返回一个“普通的 DOM 节点”。它混合了 Element 扩展,这与 jQuery 做的事情类似。
不过,我期待着 jQuery on Rails。它有很大的潜力
Pingback: Interaction Design Blog » 博客存档 » jquery vs prototype
Jquery 真的很棒,我在 railsforum.com 上发布了关于需要一个 jquery on rails 项目的帖子,但发现你正在着手开发这个项目。
我真的很佩服。不过我在 JQuery 中发现了一个 bug。
假设我有一个 id 为 yo 的输入字段。
如果我想获取该值,$(‘#yo’).value 不起作用。只有 $(‘#yo’).get(0).value 有效。对我来说,这很奇怪,因为我认为 DOM 中元素的 id 必须始终是唯一的,因此不应该需要 get(0)。无论如何,除了这一点,我真的很喜欢 JQuery。继续努力!
此外,我们需要更好的函数来处理表单。Prototype 有 Form.reset 和 Form.serialize,我发现它们非常有用。
Igwe,
这两个问题都已在 jQuery 1.0 中得到解决
$(expr).val() 返回与表达式匹配的第一个元素的值。$(expr).serialize() 会序列化表单。关于重置,是否有任何原因导致普通的 vanilla Javascript 重置无法正常工作?
Pingback: Weblogger.ch » 博客存档 » Liens
script.acul.us、Dojo 或其他效果库是否与 JQuery 兼容?我的英语不好,我是法国人……
Ghor,jQuery 有自己的效果库,叫做 Interface。可以在 http://www.eyecon.ro/interface/ 查看。不过要提醒一下:虽然 jQuery 正在过渡到 1.0 版,但使用 Interface 和最新版本的 jQuery 很可能会出现问题。这个问题很快就会解决。
jQuery 中 AJAX Updater 的示例有一个错别字,应该写成
$(‘#placeholder’).load(url, par);
Jörn,
我假设你想执行一个 GET 请求,并且 par 是一个可以粘贴到 URL 末尾的查询字符串。
我真的很喜欢 JQuery 背后的理念,它充满了 bug。当我用它制作页面(没什么特别的,一些 JQuery 表达式)时,Firefox 在 Linux 上多次停止运行,速度非常慢,有时还会在 Explorer 上出现问题。它的发展速度太慢了。所以理念很好,但我希望用它来开发。:)
无论如何,说回正题:我认为 Prototype 的语法并没有那么糟糕,它比 JQuery 的更节省内存。
Andras,
目前 jQuery 中的关键 bug 是,对于错误的表达式没有错误处理。你可能写了一个无法正确解析的 jQuery 表达式(可能是错别字,也可能是创建的表达式不正确),而 jQuery 没有异常处理程序,它经常会失败。
这是一个非常重要的缺陷,John 说他计划发布一个开发者插件,为其添加错误处理(他说,在生产环境中实现它将占用大量内存)。
当然,还存在一些 bug,但 jQuery 团队一直在快速修复 bug(查看 http://proj.jquery.com/dev 上的 jQuery Trac),1.0 版应该会更加稳定。
另外,并不是 Prototype 的语法不好,而是 jQuery 的整体设计理念远远优于它(这会产生更简洁、更短的代码)。
我已经能够在生产环境中使用 jQuery,它非常稳定。
Pingback: Devlounge | Ajax on Rails - Prototype vs JQuery
Pingback: Dr Nic on Ruby on Rails » Ajax on Rails - Prototype vs JQuery
关于 Mislav 的评论和你的更新,我想补充一点,Prototype 为 Element 类提供了一个方法(称为 addMethods),它可以扩展 Element 类,以提供你所倡导的这种简写方式。
查看我在这个主题上的帖子 (http://tobielangel.com/bytesandpieces/2006/08/16/extending-prototype-a-better-syntax-for-dom-insertion/),以及我对 Prototype 的小型扩展包,它可以实现更简洁的 JQuery 式语法
$(‘myUl’).insertionTop(‘a new list item’)
而不是
new Insertion.Top(…).
不过,使用 Prototype 进行迭代很快就会变得很繁琐。
Yehuda:表达式没有问题,因为它在浏览器没有挂起时运行良好。最新的开发版本似乎可以正常工作,我希望它能够正常工作。
更简洁的设计:我写了一个非常非常好的简短表达式来创建一个图形菜单,它可以正常工作。我很喜欢它。但是它太慢了,我不得不重新编写它以进行优化。目前它速度很快,但与 jQuery 的理念无关。
我真的很喜欢它,我想使用它,但我不能。我希望 1.0 版会更快、更好。
Andras
酷。据我所知,jQuery 1.0 版更快,我相信 John 已经将重点放在速度优化上。也就是说,为了简单起见,你总是需要做出一定的牺牲。理想情况下,它不会成为阻碍。
感谢 ehuda Katz 的链接和你的回答,我现在明白了 :D
我认为我会选择这个库来开发我的未来应用程序,但我必须先进行测试。
Ghor,
jQuery 是一个非常前瞻性的框架,你一定能够在未来的应用程序中使用它。它目前处于过渡阶段,但这个阶段很快就会结束。
jQuery 的一个很好的结构特点是,开发者强烈支持自动化测试。事实上,构建 jQuery 的构建脚本也可以自动构建 jQuery 的测试套件。
所以,与其他一些框架相比,你不必太担心测试(虽然 scriptaculous 确实有一个不错的手动测试套件)。
请关注!
感谢你的帖子,我昨晚深入研究了 jQuery… 我印象深刻!
这是我漫无边际的想法的产物:http://tobielangel.com/bytesandpieces/2006/08/23/jquery-a-serious-prototype-contender/.
欢迎任何评论。
此致,
Tobie
您好,
你的网站 (http://www.yehudakatz.com/) 不应该是基于 jQuery(而不是 behaviour + prototype + effects)的“非常稳定网站”的示例吗?
顺便说一下,我不确定网站是故意缺乏内容,还是某个奇怪的 IE6.0 bug...
比较两个框架和故意贬低其中一个框架是不同的。我讨厌 Rails 社区这种态度,它让我更倾向于其他框架。我真的很喜欢 jQuery——但如果它的社区要走这条路,我将不得不寻找其他选择……。
Kyzysztof
感谢你的评论。就像我在文章中说的,目前,使用 Rails 和 jQuery 存在困难。我的网站是一个 Typo 博客,它使用 Prototype,因为 Rails 使用 Prototype。事实上,我的专业 Rails 项目通常也使用 Prototype(而且我喜欢 Rails 的 RJS)。
我在 Java 项目和 PHP 项目中都很好地使用了 jQuery。特别是,我重新设计了一个内部网站,利用 jQuery 做了一些非常棒的事情(我能够将以前在 5-6 个页面上的管理面板移到一个 AJAX 页面中)。
此外,我的网站目前没有内容,因为我昨天才建立它。它以前是一个非常简单的网站,只有一些基本的个人信息。
Anselm
我并没有打算贬低 Prototype。因为这篇文章是在 jQuery 博客上发布的,我显然更偏向 jQuery,但我并没有故意贬低 Prototype。就像我说的,我曾用 Prototype 取得过不错的效果,Encytemedia 发布的一些技巧确实很有用,也让我对这个框架有了更深的了解(尽管我真的希望有更好的文档来介绍像 invoke 这样的技巧,这些技巧真的应该改变 Prototype 开发人员的编码方式)。
再说一次,我喜欢 Prototype。它是一门很棒的语言。我更喜欢 jQuery 的主要原因是,它的总体理念更符合我对 JavaScript 编码的理解。
Pingback: Ajaxian » Framework Disagreement: JQuery: (Mis)leading the Pack
我尝试过在 prototype 的元素类中添加自己的方法,以便所有 DOM 节点都可以自动继承它们,从而为我提供基本与 jQuery 相似的功能。我发现,我添加的方法越多,整个过程就越慢,尤其是在 IE 中。如果你只需要操作页面上的几个节点,这不是什么大问题,但当你操作数十个节点,并创建新的节点时,速度下降就会很明显。我更喜欢 jQuery 的语法,但只要 IE 存在,我认为它就不是一个实用的解决方案。
Joseph
你尝试过测试 jQuery 实际的速度吗?John 做了一些很棒的事情来提高使 jQuery 工作的技巧的速度,我在 IE 中没有遇到任何重大速度问题,尽管它比 Firefox 稍微慢一点。
Pingback: jQuery 1.0 en flamewar | Scriptorama
Pingback: jQuery 1.0 ha salido para mostrarnos la luz - aNieto2K
Pingback: jurriaanpersyn.com » Blog Archive » BarCamp Brussels 2006 - 16PM - 17:30PM
Pingback: jQuery und Jamal - flying sparks
Pingback: Adam On Life » Blog Archive » Prototype vs JQuery?
Pingback: kchlog » Blog Archive » jQuery vs. Prototype: pointless
Pingback: Sohum’s Stuff — RSS Import » jQuery on Rails
Pingback: jQuery on Rails « Sohum’s Stuff
Pingback: geekgrl.net » jQuery vs Prototype - WordPress Gone Astray?
由于显而易见的原因(Prototype 核心是 Rails 的一部分),jQuery 永远不会得到 Rails 团队的官方“认可”。所以别再浪费口舌了。
我不特别需要 Rails 团队认可 jQuery。我只是希望那些更喜欢 jQuery 操作方式的人能够将 jQuery(一个很棒的库)与 Rails(一个很棒的框架)一起使用。
在过去几个月里,我在这方面取得了一些进展,希望很快就能发布公告。
Pingback: IAMWW | blog | links for 2007-02-02
Pingback: links for 2007-02-02 - IAMWW
顺便说一下,这里有一个有趣的基准测试,比较了 Prototype 和 jQuery 的性能
http://ajaxian.com/archives/benchmark-prototype-and-jquery
你们对此有何看法?
据我所知,jQuery 受到许多人的欢迎,因为它体积小巧,行为可爱。
非常棒的文章。我真的很不喜欢 Prototype 的大小,一直在寻找替代方案。我经常看到一些 jQuery 代码,但从未想过为什么 jQuery 会更好,仅仅因为你可以将方法链接在一起。
感谢这篇文章,我知道 jQuery 背后的理念非常棒,而且在我访问这个网站之前看到的那些速度测试也表明 prototype 和 jQuery 性能相当。
我会在一些未来的项目中尝试 jQuery,以对其进行测试。在写这篇文章的时候,jQuery 显然还没有超过 1.0 版本号。
我提到的那些速度测试是针对 1.1.2dev 版本的,结果非常有希望。
希望我的开发能够顺利进行,不会发现 jQuery 的 bug。
感谢这篇文章,它真的让我大开眼界!
该死,我必须更正上面我的评论:我提到的那些速度测试清楚地表明,prototype 比 jQuery 快 26 倍。
我没有读懂正确列的值。唯一一个比 prototype 稍微慢一点的框架是 MooTools 1.2dev。
尽管如此,我仍然会尝试 jQuery,因为我喜欢它背后的理念;)
http://encytemedia.com/blog/articles/2006/08/23/jquery-mis-leading-the-pack
感谢你提供这篇有用的文章,也许你可以在将来访问我的网站。
Pingback: Design By Tim » Blog Archive » jQuery for the non-visually impared
这篇文章说服我将我的网站转换,到目前为止,我非常喜欢这个决定!jQuery 太棒了。
Pingback: The Five JavaScript Libraries - Scatterism
Pingback: Phil Rathe.com » jQuery + Rails ( Part 1 )
Pingback: Phil Rathe.com » jQuery + Rails ( Part 1 )
Pingback: Prototype en JQuery, ‘t vervolg « CoochieHoochieMan