Skip to content

Latest commit

 

History

History
98 lines (78 loc) · 3.58 KB

02-模块化加载&防冲突处理.md

File metadata and controls

98 lines (78 loc) · 3.58 KB
title date
02-模块化加载&防冲突处理
2017/02/21 14:47:10

0、模块化加载

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 就实现了模块化加载。

1、防冲突处理

当一个库可能会挂载属性到全局变量的时候,那么就要考虑全局变量覆盖这个问题。

比如说 jQuery 会挂载到 window.jQuerywindow.$ 上,那万一这两个属性已经被其他库使用了,那我们引入 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;