一、兼容CommonJS和CommonJS-like
1.什么是CommonJS
它是一种JavaScript(以下全部称为js)语言的模块化规范,是一种思想,其最终目标在于使js能够在更多环境下运行,而不只是浏览器
CommonJS是一种不同于普通js的规范,它使得js具有模块化,能够脱离浏览器来执行js语句
2.为什么兼容
在一般js中,调用jquery(以下全部称为jq)方法是需要将jq对象挂接到全局的window对象上的,而在CommonJS中,没有现成的window对象,但可以通过require来获取jq对象
3.module对象
在Node.js中,Module是一个构建函数,所有的模块儿都是此函数的实例。每个模块内部都有一个module对象,代表当前模块,其中module.exports属性是用来对外输出值,将接口暴露出去
4.源码
( function( global, factory ) {
"use strict";
if ( typeof module === "object" && typeof module.exports === "object" ) {
module.exports = global.document ?
factory( global, true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "jQuery requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
//此处省略各种方法
if ( typeof noGlobal === "undefined" ) {
window.jQuery = window.$ = jQuery;
}
return jQuery;
});
5.解读源码
-
整体结构
( function( global, factory ) { })( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { return jQuery; });
整体来看这是一个(function(){})()结构的立即执行函数,这是一个匿名函数,这个函数可以自己进行执行,匿名函数最大的优点是不会造成全局变量污染
(function(arg1,arg2){ })(param1,param2) //相当于 function test(arg1,arg2){ //上面是一个匿名函数,为了更好的表达,我将给函数起一个名字 } test(param1,param2);
-
“use strict”;
这是js的严格模式,其作用是使得js代码运行时实行更加严格的解析和错误的处理,详细内容请自己查询
-
代码解读1
( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { //此处省略各种方法 if ( typeof noGlobal === "undefined" ) { window.jQuery = window.$ = jQuery; } return jQuery; });
-
这里是调用了匿名的函数,然后将两个值传进去,
typeof window !== "undefined" ? window : this
是第一个参数,function( window, noGlobal )
这整个函数是第二个参数 -
第一个参数判断当前是否存在window对象,如果存在就把该对象传给global,否则将当前对象传给global;
-
第二个参数是jq的工厂函数,其中包含了所有jq方法,将该函数传给了factory
-
在第二个参数方法中,判断了是否定义了noGlobal,若有则直接返回jq对象,否则将jq对象添加到window中
-
-
代码解读2
( function( global, factory ) { "use strict"; if ( typeof module === "object" && typeof module.exports === "object" ) { module.exports = global.document ? factory( global, true ) : function( w ) { if ( !w.document ) { throw new Error( "jQuery requires a window with a document" ); } return factory( w ); }; } else { factory( global ); } } )
- 这是一段匿名函数,其作用就是判断当前运行环境,将js对象以不同的方式暴露
- global是全局的意思,factory是工厂的意思,很明显global是一个全局变量,factory是jq的工厂变量
- 首先判断是否存在module是否为对象,并且module中的module.exports是否为对象,其实就是判断module中是否存在exports,也就是判断当前是否在CommonJS环境中,若在CommonJS环境中,则将jq对象赋给module.exports来暴露jq对象
- 其中
global.document
用来判断当前是否存在document对象(比如Node.js没有该属性),也就是判断此时是否在浏览器运行,若在浏览器运行则直接调用factory方法来创建jq对象(这里有两个参数,第二个用来跳过代码解读1中的添加window属性)赋值给module.exports,否则构建一个函数用来接收window对象并赋值给module.exports,判断传入的window是否有document属性,没有报告错误,有则执行factory方法(没有第二个参数,所以noGlobal没有定义)将jq添加到window中 - 如果不是在CommonJS环境中,则直接调用factory方法来将jq对象添加到window中
-
总之,jq强制了当前环境必须存在window对象,并将jq对象添加到window中