jQuery 中,noConflict 是用来处理全局变量冲突、释放变量控制权的一个重要方法。
我们知道,jQuery 对外提供了两个常用的全局变量:$ 和 jQuery。虽然一般情况下只使用 jQuery 时不会出现冲突,但如果网页中同时引入了多个 JavaScript 类库,或者自定义了 $、jQuery 等全局变量,就有可能产生变量冲突。
jQuery 提供的 noConflict 函数很好地解决了这个问题。无论是 $ 还是 jQuery 发生冲突,都可以通过相应的方式进行处理。接下来就来看一下 jQuery 是如何实现变量冲突处理的。
先来看一下 jQuery 源码中 noConflict 的实现:
(function(window, undefined) {
// Map over jQuery in case of overwrite
var _jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$;
jQuery.extend({
noConflict: function(deep) {
if (window.$ === jQuery) {
window.$ = _$;
}
if (deep && window.jQuery === jQuery) {
window.jQuery = _jQuery;
}
return jQuery;
}
});
}(window));这里的 jQuery.extend 是用来给 jQuery 扩展静态属性和方法的,可以简单理解为直接在 jQuery 上增加了一个 noConflict 方法。
在匿名函数内部,首先定义了 _jQuery 和 _$ 两个内部变量,分别保存当前的 window.jQuery 和 window.$:
var _jQuery = window.jQuery,
_$ = window.$;
这样做的作用,是在 jQuery 接管这两个全局变量之前,先把它们原来的状态保存起来,以便后面发生冲突时进行恢复。
noConflict 可以处理 $ 和 jQuery 这两个变量的冲突。默认情况下只释放 $:
jQuery.noConflict();
如果传入 true:
jQuery.noConflict(true);
则会同时释放 $ 和 jQuery 两个全局变量。
来看下面这段代码:
if (window.$ === jQuery) {
window.$ = _$;
}它的意思是:只有当前的 $ 仍然指向 jQuery 时,才把 $ 恢复成 jQuery 加载之前保存的值。
对于 jQuery 变量也是一样:
if (deep && window.jQuery === jQuery) {
window.jQuery = _jQuery;
}当开启深度冲突处理,并且当前的 window.jQuery 仍然指向 jQuery 时,才把它恢复成之前保存的 _jQuery。
这里的判断非常重要。它的作用是避免已经被其他代码重新定义的变量再次被覆盖。
例如:
// 引入 jQuery 库
var $ = "String";
var jq = jQuery.noConflict();
var jQuery = "This is a line";
var j = jq.noConflict(true);
console.log($);
console.log(jQuery);
如果没有:
window.$ === jQuery
这个判断,那么 noConflict() 在恢复 $ 时,可能会直接把后来重新定义的 $ 覆盖掉。
同样,如果没有:
window.jQuery === jQuery
这个判断,那么开启深度冲突处理后,后来重新定义的 jQuery 变量也可能再次被之前保存的值覆盖。
所以,noConflict 的实现原理其实并不复杂:先保存 jQuery 接管 $ 和 jQuery 之前的值,在需要时恢复这些值,同时判断当前变量是否仍然由 jQuery 控制,避免误覆盖后来重新定义的变量。
整个运行流程如下图

最后,noConflict() 返回的是 jQuery 本身,因此可以把它保存到另一个变量中继续使用:
varjq=jQuery.noConflict();jq("div").hide();这样,即使 $ 已经释放,仍然可以通过 jq 来使用 jQuery。
评论0
欢迎分享你的看法,也欢迎补充不同的实践经验。