jQuery是目前使用最广泛的前端框架之一,有大量的第三方库和插件基于它开发。为了避免全局命名空间污染,jQuery提供了jQuery.noConflict()方法解决变量冲突。这个方法,毫无疑问,非常有效。遗憾的是,jQuery的官方文档对该方法的描述不够清晰,许多开发者并不清楚当他们调用jQuery.noConflict()时,究竟发生了什么,从而导致在使用时出现了许多问题。尽管如此,jQuery.noConflict()背后实现原理依然值得Web开发者学习掌握,成为解决类似全局命名空间污染问题的利器。

jQuery.noConflict()的作用?

  jQuery.noConflict()的存在只有一个目的:它允许你在同一个页面加载多个jQuery实例,尤其是不同版本的jQuery。你可能会觉得奇怪,为什么要在一个页面加载/使用多个不同版本的jQuery对象呢?一般而言,有两种情况。第一种情况,你的业务代码采用了最新版的jQuery库,而你选用的第三方插件依赖的更早版本的jQuery库;第二种情况,你正维护着一个系统,它已有的业务代码由于各种原因,引用了较老版本的jQuery库,你新开发的模块采用的是其他版本的jQuery库。不论哪种情况,你都不得不面对,jQuery对象/方法冲突的问题。幸运的是,jQuery.noConflict()帮你解决了这个烦恼。

jQuery被加载时发生了什么?

  当jQuery被页面引用/加载时,它被封装在一个自执行函数(匿名函数)里,它提供的所有一切变量、函数、对象都在匿名函数内部的可执行环境内,外部环境无法调用,以防止全局命名空间污染。

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

jQuery在匿名函数内部定义了两个全局对象:jQuery$,把自己暴露给外部环境。开发者习惯使用的各种公共方法都是通过这两个对象进行访问的,如jQuery.ajax(),jQuery.css()等。在最初,它们指向匿名函数内部的同一个对象jQuery(私有变量),通过它访问匿名函数内部的私有变量和函数。这使得匿名函数在自执行后其内部的私有变量和函数仍然进驻在内存里,不会被javascript的垃圾回收机制清除。

window.jQuery = window.$ = jQuery;

  当jQuery被页面加载后,当前页面有可能已经存在了jQuery$这两个全局变量(比如,加载了其它的第三方库,其内部也定义了它俩),这就会导致已经存在的对象被覆盖(全局命名空间污染)。为了解决这个问题,jQuery在内部先将已经存在的全局变量缓存起来,保存在私有变量_jQuery_$中,供后续调用。所以,如果页面在加载jQuery库时,还不存在jQuery$对象,那么_jQuery_$都是undefined;否则,它们都会保存对已有jQuery$的引用(也许来自之前引用的第三方库或是不同版本的jQuery库)。之后,jQuery会像上文说描述的那样,覆盖这两个全局变量并将自己暴露给外部环境。至此,页面上的全局变量jQuery$已经指向刚刚引入的jQuery库。

// Map over jQuery in case of overwrite
_jQuery = window.jQuery, // Map over the $ in case of overwrite
_$ = window.$, // Otherwise expose jQuery to the global object as usual
window.jQuery = window.$ = jQuery;

jQuery.noConflict()的神奇效果?

  假设你维护的系统已经引用了1.7.0版本的jQuery库,而你在新添加的功能里引用了1.10.2版本的jQuery库。那么,还有办法重新使用jQuery 1.7.0 或是同时使用两个版本的jQuery库吗?答案是肯定,那就是jQuery.noConflict()。实际上,利用jQuery.noConflict(),你可以立刻把全局变量jQuery$重新指向之前引用的对象。很神奇吧?这就是为什么jQuery在对外暴露自己前内部缓存了之前引用的对象。

  jQuery.noConflict()接受一个可选的布尔值参数,通常默认值是false。这个参数会带来什么影响呢?其实,很简单。如果调用jQuery.noConflict()或是jQuery.noConflict(false),只有全局变量$会被重置恢复成之前的引用值;如果调用jQuery.noConflict(true),那么全局变量jQuery$都会被重置恢复成之前的引用值。这一点非常重要,建议牢记。当你调用jQuery.noConflict(false/true)之后,它会返回当前jQuery的实例,利用这个特性我们可以实现jQuery的重命名。

// "Renaming" jQuery
var jayquery = jQuery.noConflict( true );
// Now we can call things like jayquery.ajax(), jayquery.css(), and so on

我们再来看一个代码片段,测试一下是否真正理解了神奇的noConflict()

<!-- jQuery and $ are undefined -->

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- jQuery and $ now point to jQuery 1.10.2 --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js">
<!-- jQuery and $ now point to jQuery 1.7.0 --> <script>jQuery.noConflict();</script>
<!-- jQuery still points to jQuery 1.7.0; $ now points to jQuery 1.10.2 --> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js">
<!-- jQuery and $ now point to jQuery 1.6.4 --> <script>var jquery164 = jQuery.noConflict( true );</script>
<!-- jQuery now points to jQuery 1.7.0; $ now points to jQuery 1.10.2; jquery164 points to jQuery 1.6.4 -->

避免第三方库的冲突

  以上的代码片段展示了如何解决多版本jQuery的冲突。接下来,我们尝试解决jQuery库和第三方库的冲突,下面出现的代码片段在jQuery的官方文档中都有,有兴趣的程序猿可以仔细阅读官方文档体会其中的区别。

直接使用No-Conflict模式

  使用No-Conflict模式,其实就是对jQuery进行重命名,再调用。

<!-- 采用no-conflict模式,jquery.js在prototype.js之后被引入. -->
<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script> var $j = jQuery.noConflict();
// $j 引用了jQuery对象本身. $j(document).ready(function() {
$j( "div" ).hide();
}); // $ 被重新指向prototype.js里定义的对象
// document.getElementById(). mainDiv below is a DOM element, not a jQuery object.
window.onload = function() {
var mainDiv = $( "main" );
} </script>

使用自执行函数封装

  使用这种方式,你可以在匿名函数内部继续使用标准的$对象,这也是众多jQuery插件采用的方法。需要注意的是,使用这种方法,函数内部无法再使用prototype.js定义的$对象了。

<!-- jquery.js在prototype.js之后被引入. -->
<script src="prototype.js"></script>
<script src="jquery.js"></script>
<script> jQuery.noConflict(); (function( $ ) {
// Your jQuery code here, using the $
})( jQuery ); </script>

使用标准jQuery(document).ready()函数

  如果jQuery库在其它库之前引入,那么jQuery内部定义的jQuery$会被第三方库覆盖,这时候再使用noConflict()已经没有什么意义了。解决的方法很简单,直接使用jQuery的标准调用方式。

<!-- jquery.js在prototype.js之前被引入. -->
<script src="jquery.js"></script>
<script src="prototype.js"></script>
<script> // Use full jQuery function name to reference jQuery.
jQuery( document ).ready(function() {
jQuery( "div" ).hide();
}); // 或者
jQuery(function($){
// Your jQuery code here, using the $
}); // Use the $ variable as defined in prototype.js
window.onload = function() {
var mainDiv = $( "main" );
}; </script>

三分钟玩转jQuery.noConflict()的更多相关文章

  1. 十分钟玩转 jQuery、实例大全(参考自博主索宁)

    十分钟玩转 jQuery.实例大全(参考自博主索宁) 一.简介 书写规则 支持链式操作: 在变量前加"$"符号(var $variable = jQuery 对象): 注:此规定并 ...

  2. 三分钟玩转微软AI量化投资开源库QLib

    更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流. 微软QLib简介 微软亚洲研究院发布了 AI 量化投资开源平台"微矿 Qlib".Q ...

  3. 十分钟玩转 jQuery、实例大全

    一.简介 定义 jQuery创始人是美国John Resig,是优秀的Javascript框架: jQuery是一个轻量级.快速简洁的javaScript库.源码戳这 jQuery对象 jQuery产 ...

  4. 每天5分钟 玩转OpenStack 目录列表

    最近在学习 OpenStack 的相关知识,一直苦于 OpenStack 的体系庞大以及复杂程度,学习没有进度,停滞不前.偶然机会在 51CTO 上发现了一个热点的专题关于 OpenStack 的,题 ...

  5. jQuery.noConflict() 函数

    jQuery.noConflict()函数用于让出jQuery库对变量$(和变量jQuery)的控制权. 一般情况下,在jQuery库中,变量$是变量jQuery的别名,它们之间是等价的,例如jQue ...

  6. window.onload多个共存 - 借鉴jQuery.noConflict的思路

    一.背景  window.onload方法只能存在一个,如果多次赋值给window.onload,则后者会覆盖前者. 二.浅谈jQuery.noConflict的实现方式 1)源代码 // 简化抽离出 ...

  7. 学习 OpenStack 的方法论 - 每天5分钟玩转 OpenStack(150)

    作为 OpenStack 的核心教程,我们已经到了最后总结的部分. OpenStack 目前已经有好几十个模块,本教程讨论的是最最重要的核心模块:Keystone,Nova,Glance,Cinder ...

  8. cloud-init 典型应用 - 每天5分钟玩转 OpenStack(174)

    本节介绍几个 cloud-init 的典型应用:设置 hostanme,设置用户初始密码,安装软件. 设置 hostname cloud-init 默认会将 instance 的名字设置为 hostn ...

  9. 如何共享数据?- 每天5分钟玩转 Docker 容器技术(41)

    数据共享是 volume 的关键特性,本节我们详细讨论通过 volume 如何在容器与 host 之间,容器与容器之间共享数据. 容器与 host 共享数据 我们有两种类型的 data volume, ...

随机推荐

  1. Nodejs学习笔记(二)——Eclipse中运行调试Nodejs

    前篇<Nodejs学习笔记(一)——初识Nodejs>主要介绍了在搭建node环境过程中遇到的小问题以及搭建Eclipse开发Node环境的前提步骤.本篇主要介绍如何在Eclipse中运行 ...

  2. 谈谈Android 6.0运行时权限理解

    前言 谷歌在2015年8月份时候,发布了Android 6.0版本,代号叫做“棉花糖”(Marshmallow ),其中的很大的一部分变化,是在用户权限授权上,或许是感觉之前默认授权的不合理,现在6. ...

  3. Cordova webapp实战开发:(7)如何通过简单的方法做到,不重新发布APP来修复bug、增加功能、或者躲开苹果的一些严格审核?

    到<Cordova webapp实战开发:(6)如何写一个iOS下获取APP版本号的插件?>为止,我们已经大体学会了如何使用Cordova了,那些都是使用Cordova的开发者必备的技能. ...

  4. hadoop中MapReduce多种join实现实例分析

    转载自:http://zengzhaozheng.blog.51cto.com/8219051/1392961 1.在Reudce端进行连接. 在Reudce端进行连接是MapReduce框架进行表之 ...

  5. 谷歌插件Image downloader开发之 content script

    自己运营了一个公众号,在发文章的时候,需要在网上找一些图,而有些网站的图片可能隐藏在属性或者背景图中,要下载的时候经常审查元素,查看源码,不太方便,最近在看一些谷歌插件的api,便顺手做了一个插件Im ...

  6. linux专题三之如何悄悄破解root密码(以redhat7.2x64为例)

    root用户在linux系统中拥有至高无上的权限.掌握了root密码,差不对可以对linux系统随心所欲了,当然了,root用户也不是权限最高的用户. 但是掌握了root密码,基本上够我们用了.本文将 ...

  7. 【Swift学习】Swift编程之旅(四)基本运算符

    Swift支持大部分标准C语言的运算符, 且改进许多特性来减少常规编码错误.如赋值符 = 不返回值, 以防止错把等号 == 写成赋值号 = 而导致Bug. 数值运算符( + , -, *, /, %等 ...

  8. ASP.NET MVC动态生成网站菜单及子菜单

    在开发ASP.NET MVC网站时,Insus.NET想实现动态产生网站的主菜单及子菜单. 你需要在网站管理后台管理此2张表(Menu,SubMenu)的信息,添加,删除,编辑,更新等. Sequen ...

  9. asp.net应用程序生命周期

    asp.net应用程序生命周期(流程文字描述版) 请求——>IIS——>ISAPI映射——>交给asp.net(即为IIS的扩展)——>通知Application类创建一个应用 ...

  10. easyui-layout 布局自适应

    最近在把以前写的一个项目改成用easyui做前端.过程中遇到了不少问.其中一个就是datagrid不能很好的布.想了好多办法都有局限.最后想到会不会是布局的问题,经过实,最后问题解. 1:比如在项目中 ...