title | date |
---|---|
02-模块化加载&防冲突处理 |
2017/02/21 14:47:10 |
jQuery
在之前的版本(具体不记得是哪个版本以前了)中,是不支持模块化加载的。
当前,模块化作为一个趋势,jQuery
也增加了对模块化的支持,当今最流行的的模块规范是 UMD
,简单点说就是判断各种环境,然后选择合适的方式加载。
来看下具体的实现:
//首先是一个IIFE,避免污染全局变量
( function( global, factory ) {
"use strict";
// 判断是否是模块化加载
// 如果是CMD加载器,那么会有 module 和 module.exports 属性
if ( typeof module === "object" && typeof module.exports === "object" ) {
// 如果有document,那就算是浏览器环境,那么直接导出jQuery
module.exports = global.document ?
// 注意, factory第二个参数是true,也就是说不会挂载到全局变量上(模块化加载不需要挂载到window上)
factory( global, true ) :
// 虽然看起来是模块化加载,但是没有找到window对象,这个时候就导出一个factory,需要手动传入window对象。
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
// 如果不是加载器加载,那么就直接把window或者this传递给 jQuery factory
factory( global );
}
// Pass this if window is not defined yet
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
// jQuery本身的逻辑代码
// 注意,jQuery也支持了AMD方式加载。
if ( typeof define === "function" && define.amd ) {
define( "jquery", [], function() {
return jQuery;
} );
}
});
通过以上代码实现,jQuery
就实现了模块化加载。
当一个库可能会挂载属性到全局变量的时候,那么就要考虑全局变量覆盖这个问题。
比如说 jQuery
会挂载到 window.jQuery
和 window.$
上,那万一这两个属性已经被其他库使用了,那我们引入 jQuery
不就把别人的库覆盖了么。
作为一个完备的库,jQuery
也处理了这种场景。那就是防冲突方法。
看一下具体的实现:
// 在实现防冲突时,要注意代码的顺序
// 首先先用局部变量,把要挂载的属性备份一次。
var
// Map over jQuery in case of overwrite
_jQuery = window.jQuery,
// Map over the $ in case of overwrite
_$ = window.$;
// 实现一个冲突方法,当调用该方法时,就会把之前保存的全局变量进行还原。
// deep的意思就是是否要还原jQuery这个属性,因为jQuery并不是一个常用的属性,所以一般不会被其他库占用。
jQuery.noConflict = function(deep) {
if (window.$ === jQuery) {
window.$ = _$;
}
if (deep && window.jQuery === jQuery) {
window.jQuery = _jQuery;
}
// 冲突之后,总要挂载吧,通过return jQuery,就能返回jQuery,这个时候可以任意挂载到你想要的属性。
// 实例代码: window.abcde = jQuery.noConflict();
return jQuery;
};
// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
// 如果不是非全局(如果是双重否定,实际就是如果是全局)
if (!noGlobal) {
// 那么就设置到全局变量,这个时候已经把全局属性覆盖了。
window.jQuery = window.$ = jQuery;
}
return jQuery;