功能
jQuery API文档中对noConflict方法的描述是:"释放jQuery对变量$的控制权"。( ′◔ ‸◔`)不是很明确,慢慢解释下。
我们都知道jQuery库占用了全局变量$(是变量jQuery的别名), 但是其他JS库也可以使用该变量了(比如zeptoJS, prototypejs)。当项目中同时引用了jQuery和其他占用全局变量$的库时,可能会导致变量$冲突。所以jQuery在给全局变量$赋值的时候先保存当时全局变量$已经存在的值,然后通过jQuery.noConflict方法把原来保存的值重新赋值给全局变量$。
类似的手法noConflict方法也实现了对jQuery变量的释放控制(主要用于同时引入多个版本的jQuery)。
这里只对全局变量$的处理进行解析,jQuery变量的处理方式类似。
实现
jQuery v3.2.1中noConflict方法的完整实现(解释见注释):
var
// 保存此时全局变量jQuery的值,可能其他版本的jQuery已经加载了
_jQuery = window.jQuery,
// 保存此时全局变量$的值,可能其JS库已经占用了全局变量$
_$ = window.$;
jQuery.noConflict = function( deep ) {
// 如果此时全局变量$还属于jQuery,则把全局变量$在jQuery初始化时的值_$重新赋值给$。
if ( window.$ === jQuery ) {
window.$ = _$;
}
// 如果参数deep为true且此时全局变量jQuery还属于当前版本的jQuery,则把全局变量jQuery在当前版本jQuery初始化时的值_jQuery重新赋值给jQuery。
if ( deep && window.jQuery === jQuery ) {
window.jQuery = _jQuery;
}
// 返回当前版本的jQuery变量
return jQuery;
};
通过实现发现jQuery库在且只在初始化的时候会保存当时全局变量$和jQuery的值,保存的值会在方法noConflict调用的时候复原。所以其他占用全局变量$的库要先于jQuery引用,noConflit方法才能正确工作。
举例
假设有个js文件glib.js也占用了全局变量$:
;(function() {
var glib = function() {
console.log('I am from glib js');
};
window.$ = window.glib = glib;
})()
index.html 内容:
<!DOCTYPE html>
<html>
<head>
<title>jQuery</title>
</head>
<body>
<h1 id="title">hi jQuery noConflit</h1>
<script type="text/javascript" src="glib.js"></script>
<script type="text/javascript" src="../a.libs/jquery.js"></script>
<script type="text/javascript">
;(function() {
var text = $('#title').text(); // 变量$是jQuery
console.log(text);
$.noConflict(); // jQuery释放$变量,这样变量$的是glib中定义的
$(); // 输出"I am from glib js"
})()
</script>
</body>
</html>
注意一定在jQuery前引用glib.js文件。这样当jQuery初始化时,全局变量已经被glib占用了。
其他
调用noConflict方法释放全局变量$的控制权后,可以使用变量jQuery使用代替,或者给jQuery另其一个别名($也只是一个别名啊)
<script type="text/javascript">
;(function() {
var text = $('#title').text(); // 变量$是jQuery
console.log(text);
var j = $.noConflict(); // 新的别名j
// 方式1
console.log(jQuery('#title').text()); // 这里直接使用jQuery变量
// 方式2
console.log(j('#title').text()); // 这里使用新的别名j
})()
</script>
怎么还可以使用变量$呢?一般通过立即执行函数方式继续使用全局变量$
<script type="text/javascript">
;(function() {
var text = $('#title').text(); // 变量$是jQuery
console.log(text);
var j = $.noConflict(); // 新的别名j
// 方式1
console.log(jQuery('#title').text()); // 这里直接使用jQuery变量
// 方式2
console.log(j('#title').text()); // 这里使用新的别名j
// 方式3
;(function($){
console.log(j('#title').text()); // 在立即执行函数里继续使用变量$
})(jQuery) // 变量jQuery当作参数传入
})()
</script>