为什么 jQuery 的理念更好

发布于 作者

关于 jQuery 和 Prototype 之间代码大小的差异,本博客上已经发布了很多文章。这些文章的基本前提(我同意)是,由于 jQuery 代码的结构方式,与 Prototype 相比,框架中所有典型的 Javascript 设计模式都变得更短、更简单。

很长一段时间,我一直是一个公认的 Prototype 迷。当我开始做 Rails 工作时,我发现了这个框架,对于 Rails 开发人员来说,几乎没有其他选择。Prototype 以其所有丑陋的方式,被烘焙到 Rails 中,很难放弃 Rails 通过手工编码 Javascript 提供的生产力优势。更进一步地说,这就是我开始着手开发 jQuery on Rails 的原因,它旨在让 Rails 开发人员能够使用 jQuery 作为 Prototype 的直接替代。

但回到这篇文章的主题,jQuery 的编程理念比仅仅是代码大小,更根本的不同。事实上,这种理念上的差异与 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’) 将在页面上的每个 <p> 之后添加 ‘some HTML’。就我个人而言,我认为在我的代码中消除迭代(在大多数情况下)是使用 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 将其作为基本设计决策的方式。

关于“为什么 jQuery 的理念更好”的 55 个想法

  1. 对于我大多数项目而言,jQuery 都很出色。在其他一些项目中,我使用 Prototype,但这都是关于为要完成的任务使用最佳工具。

    对于那些抱怨的人,你们可以 *使用你们想要的任何东西*。如果你不能,那就学习如何处理多个框架并提高你的编码技能,那是你的问题。此外,正如一些人所言…… 不使用框架是因为你不同意它背后的社区?真的吗?我相信当谈到实际工作时,选择某样东西不是因为它正确,而是因为它的“社区”更好,这种做法会非常受欢迎。

    PS:我讨厌 JavaScript。该死的 AJAX 嬉皮士。

  2. Pingback: JQuery vs. Prototype | Phine Solutions

  3. Pingback: What Makes jQuery a Good Choice?

  4. jQuery 和/或 Prototype 与某些服务器端框架(例如 JSF + Richfaces,这是我的目标)的兼容性如何?
    我正在研究它们的兼容性,以及用客户端库替换基于 AJAX 的服务器端库的可能性。

  5. Pingback: the time has come: converting Prototype into jQuery