如何让 jQuery 和 prototype 共存
jQuery 和 prototype 是两个最著名的 JavaScript 框架(JavaScript: TDG 第五版的中文版,将框架翻译为帧 :-P )。
群英汇研究的开源软件,绝大多数的Web端都使用了 Prototype,这是因为 Prototype 和核心思想是增强 JavaScript 本身的编程能力,而这无疑会让程序员将其作为框架的首选。 jQuery 的问世稍微比 Prototype 晚一些,但是因为 jQuery 拥有更为简单的windows.onload 调用 “$(function() {...})” 或者稍复杂但更明显的 “$(document).ready(function() {...}) ”,让 jQuery 拥有非常多的拥趸和插件。关于这两个 JavaScript 的对比,在得空的时候,再说一说。
那么能否在一个页面中同时使用这两个框架呢?
同时使用 jQuery 和 Prototype 框架,大部分原因是页面中已经使用了一种框架(如 Prototype),而希望通过添加另外的一个框架的某个插件,迅速的得到某个效果(如默个 jQuery 插件)。
实际上 jQuery 和 Prototype 在解决了命名空间的冲突之后,共存是完全可能的。
jQuery 和 Prototype 的命名空间冲突
Prototype JS框架为 JavaScript 增加了相当多的命名空间:$, $$, $A, $H, $w, Class, Prototype, Hash, Event, ... 而 jQuery 和 Protype 相比则简单许多,因为整个 jQuery 代码就是一个闭包,且仅仅为JavaScript 命名空间引入两个新名字: $ 和 jQuery。 很显然 $ 就是两者冲突的焦点,只要解决 $ 的冲突问题,两者即可共存。jQuery 中的$ 和冲突解决机制
jQuery 中,$ 就是 jQuery
前面说过:整个 jQuery 代码就是一个闭包,且仅仅为JavaScript 命名空间引入两个新名字: $ 和 jQuery。让我们看看 jQuery 代码:行号 1: /* 注释开始 ... 行号 15: * 注释结束 */ 行号 16: (function( window, undefined ) { ... 行号 6321: // Expose jQuery to the global object 行号 6322: window.jQuery = window.$ = jQuery; 行号 6323: 行号 6323: })(window);从上面的代码可以看出,jQuery 引入的两个全局对象名实际上指向同一个对象,即 $ 实际上就等同于 jQuery。 那么只要删除 jQuery.js 中对 $ 的定义,并在 jQuery 相关脚本中将 $ 全部用 jQuery 替代不就可以了么?
不必修改代码,jQuery 的 noConflict 方法可用于解决冲突
实际上 jQuery 已经考虑到和其他框架命名空间冲突的问题,提供一个 noConflict 方法用于冲突解决。让我们看一段 jQuery 中的代码:行号 24: // Map over jQuery in case of overwrite 行号 25: _jQuery = window.jQuery, 行号 26: 行号 27: // Map over the $ in case of overwrite 行号 28: _$ = window.$, ... 行号 363: jQuery.extend({ 行号 364: noConflict: function( deep ) { 行号 365: window.$ = _$; 行号 366: 行号 367: if ( deep ) { 行号 368: window.jQuery = _jQuery; 行号 369: } 行号 370: 行号 371: return jQuery; 行号 372: },即只要在 JavaScript 中调用 jQuery.noConflict() 后,$ 就恢复成 jQuery 调用前的命名空间,不再产生冲突。 示例:
<html> <head> <script src="prototype.js"></script> <script src="jquery.js"></script> <script> // 恢复 $ 为 Prototype 中的定义,jQuery 只使用 jQuery 名称来调用 jQuery.noConflict(); // jQuery 使用 jQuery(...) 来调用 jQuery(document).ready(function(){ // ... }); // $ 实际上是 Prototype 的调用 $('DivID').hide(); </script> </head> <body> ... </body> </html>
总结
因为 jQuery 提供了避免名字冲突的方法,而 Prototype 代码中大量引用了 $,不便修改,因此使用 jQuery 提供的机制 将 $ 为 Prototype 所用,jQuery 只使用 jQuery 调用,或者使用其他简洁的自定义别名。- 方案一:为避免冲突,jQuery 只用 jQuery 调用
<script src="prototype.js"></script> <script src="jquery.js"></script> <script> jQuery.noConflict(); </script>
- 方案二:为避免冲突并且保持简洁,jQuery 使用别名 $j 调用,不再使用 $ 甚至 jQuery
<script src="prototype.js"></script> <script src="jquery.js"></script> <script> var $j = jQuery.noConflict(true); ... $j(document).ready(function(){ ...
- 方案三:通过闭包,依旧使用 $,而且不会造成和 Prototype 的冲突
这个方法是通过闭包调用,$ 作为参数或者局部变量的方式指向 jQuery:
(function($) { // 这里 $ 指向 jQuery,也不会破坏全局的命名空间 })(jQuery);