jQuery 中对 CommonJs提供了直接支持,可以在 CommonJs模块中直接引用 jQuery 对象,这是如何实现的呢?

从 factory 函数说起

说先看 jQuery 的主体函数定义,这个函数用来返回我们定义的 jQuery 函数,所以它就是一个工厂函数 factory,在 jQuery 3.0.0 中,就是第 40 行开始,到 10037 行结束。

#   40   }( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
#10036 return jQuery;
#10037 } ) );

我们将这个函数抽取出来,简化一下,基本就是下面的样子。

#   40 function( window, noGlobal ) {

# 90 jQuery = function( selector, context ) {
# 95 };
#10031 if ( !noGlobal ) {
#10032 window.jQuery = window.$ = jQuery;
#10033 }
#10034
#10035
#10036 return jQuery;
#10037 };

从函数定义可以看到,它需要两个参数,第一个参数就是 window,jQuery 是用来操作 document 的,document 又定义在 window 之上,jQuery 需要通过它来获取 document,以便进行进一步的 DOM 操作。第二个参数则表示是否存在全局对象,如果没有的话,则意味着 jQuery 直接运行在浏览器环境下,不是在 CommonJs 模块环境下,这样的话,就直接将 jQuery 对象挂接到全局的 window 对象上,以后,直接使用 window 来获取 jQuery 对象了。如果在 CommonJs 环境下,就不需要这样做了,因为可以通过 require 来获取 jQuery 对象,就没有必要挂接到 window 对象上了。

但是,在 #10037 行,我们并没有看到熟悉的直接执行圆括号,那么,什么时候调用了这个工厂函数呢?

注册函数

我们回头再来看开头的几行代码。

# 14 ( function( global, factory ) {
# 15
# 16 "use strict";
# 17
# 18 if ( typeof module === "object" && typeof module.exports === "object" ) {
# 19
# 20 // For CommonJS and CommonJS-like environments where a proper `window`
# 21 // is present, execute the factory and get jQuery.
# 22 // For environments that do not have a `window` with a `document`
# 23 // (such as Node.js), expose a factory as module.exports.
# 24 // This accentuates the need for the creation of a real `window`.
# 25 // e.g. var jQuery = require("jquery")(window);
# 26 // See ticket #14549 for more info.
# 27 module.exports = global.document ?
# 28 factory( global, true ) :
# 29 function( w ) {
# 30 if ( !w.document ) {
# 31 throw new Error( "jQuery requires a window with a document" );
# 32 }
# 33 return factory( w );
# 34 };
# 35 } else {
# 36 factory( global );
# 37 }
# 38
# 39 // Pass this if window is not defined yet
# 40 }( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {

这样,这个函数需要一个全局对象,和一个用来创建 jQuery 对象的工厂函数。

从 #14 到 #40 可以看到这是一个典型的直接执行函数定义,这个函数也需要两个参数,第一个就是我们所需要的 window 对象,第二个参数就是我们上面提到的用来创建 jQuery 函数的工厂函数,它已经在前面说过了,所以,我们先看一下第一个参数。

理论上讲,我们只需要将浏览器的 window 对象获取到就可以了,但是,还有一种情况是程序运行在 Node.Js 环境下,比如服务器环境下,这时候不是直接运行在浏览器环境下,也就不能直接获取 window 对象了,所以,这里检查了一下,当前是否有 window 对象,没有的化,就将 this 传进来。

#40  typeof window !== "undefined" ? window : this

在这个函数中需要做什么呢?

如果不是在 CommonJs 环境下,很简单了,直接执行工厂函数,让工厂函数将 jQuery 对象注册到 window 对象上,就可以了,这就是 #36 的作用,这里没有传递第二个参数,在 javascript 中,没有提供的参数,值就是 undefined,在用作 boolean 判断的时候,等同于 false。

如果在 CommonJs 环境下,将 jQuery 对象挂接到 module.exports 对象上,就完成任务了。

怎么知道在 CommJs 环境下呢?需要判断一下,#18 就是用来判断当前的运行环境的。

if ( typeof module === "object" && typeof module.exports === "object" ) {

CommJs 环境中会有一个 module 对象,这个对象上会有一个 exports 对象。

这样,#27, #28 也比较容易理解了,就是调用 factory 函数来创建出 jQuery 对象,将这个对象注册到 exports 对象上。这里的 noGlobal 参数传递了一个 true,就不会在 window 上再注册 jQuery 对象了。

#27 还有 global.document 是否存在的检查,别忘了,我们可能运行在非浏览器环境下。

在浏览器环境下,我们按照上述处理就可以了,如果在非浏览器环境下,就没有当前的 window 对象了,你可能自己创建了一个模拟浏览器的环境,有自己的 window 对象,这个时候的 jQuery 对象需要绑定到你的这个特殊的 window 对象上,#29 - #34 的函数定义了一个工厂函数,你需要将你的 window 对象传递进来,这个工厂函数再调用我们前面定义的工厂来创建一个绑定到指定 window 的 jQuery 函数供你使用。

jQuery 中对 CommonJs 的支持处理的更多相关文章

  1. jQuery中animate()的方法以及$("body").animate({"scrollTop":top})不被Firefox支持问题的解决

    转载请注明出处:http://blog.csdn.net/dongdong9223/article/details/50846678 本文出自[我是干勾鱼的博客] jQuery中animate()的方 ...

  2. es6 Object.assign ECMAScript 6 笔记(六) ECMAScript 6 笔记(一) react入门——慕课网笔记 jquery中动态新增的元素节点无法触发事件解决办法 响应式图像 弹窗细节 微信浏览器——返回操作 Float 的那些事 Flex布局 HTML5 data-* 自定义属性 参数传递的四种形式

    es6 Object.assign   目录 一.基本用法 二.用途 1. 为对象添加属性 2. 为对象添加方法 3. 克隆对象 4. 合并多个对象 5. 为属性指定默认值 三.浏览器支持 ES6 O ...

  3. [转载]Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结

    本文对Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法进行了详细的总结,需要的朋友可以参考下,希望对大家有所帮助. 详细解读Jquery各Ajax函数: ...

  4. Jquery中的bind(),live(),delegate(),on()绑定事件方式

    博客转载为作者:枫上善若水http://www.cnblogs.com/xilipu31/p/4105794.html 前言 因为项目中经常会有利用jquery操作dom元素的增删操作,所以会涉及到d ...

  5. JavaScript jQuery 中定义数组与操作及jquery数组操作

    首先给大家介绍javascript jquery中定义数组与操作的相关知识,具体内容如下所示: 1.认识数组 数组就是某类数据的集合,数据类型可以是整型.字符串.甚至是对象Javascript不支持多 ...

  6. jQuery中的100个技巧

      1.当document文档就绪时执行JavaScript代码. 我们为什么使用jQuery库呢?原因之一就在于我们可以使jQuery代码在各种不同的浏览器和存在bug的浏览器上完美运行. < ...

  7. jQuery中Animate进阶用法(一)

    jQuery中animate的用法你了解多少呢?如果仅仅是简单的移动位置,显示隐藏,哦!天哪你在浪费资源!因为animate太强大了,你可以有很多意想不到的用法!让我们一起研究一下吧~~ 首先要了解j ...

  8. 解决上一篇jquery中on的疑惑

    内容都是来自:http://www.365mini.com/page/jquery-on.htm.这里做一下收藏.文章的最后  疑问和解答可以解决所有的疑惑  看了之后能更好的整篇文章. on()函数 ...

  9. jquery中的ajax参数说明

    本文只作为记录,方便以后查阅. 内容原地址:$.ajax( )方法详解及案例_JQuery_wodi0007的博客_程序员博客网 http://u.cxyblog.com/28/article-aid ...

随机推荐

  1. Java框架重量级,轻量级的问题?

    一般认为,SSH为重量级.SSI为轻量级. 但轻重的概念怎么界定?

  2. [C++] Running time and Integer to String

    std::string num2str(int64_t p_vint, int8_t p_radix) { char str[48] = { 0 }; int64_t temp = 0; int64_ ...

  3. 用JS控制video暂停再播放

    模块就是用来进行封装,进行高内聚 低耦合的功能.其实各人认为ng2 的模块和.net的工程类似,如果要使用模块中定义的功能,第一步就是必须要引用它,ng2 中叫import 导入.那么我们看模块是否有 ...

  4. BZOJ 1303 CQOI2009 中位数图 水题

    1303: [CQOI2009]中位数图 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2340  Solved: 1464[Submit][Statu ...

  5. 2015年我国IT行业发展趋势分析(转)

    中国信息化建设步伐正持续推进,行业和企业信息化应用水平也在不断提高,这使得it技术与应用系统已成为企业日常工作中不可或缺的基础设施.与此同时,用户关注的重心也日益转向it系统的稳定性.系统对生产效率的 ...

  6. MAC的终端命令

    今天小研究了一下MAC的终端命令,主要为了方便调试程序用,XCODE用不来啊... 在这里记下..防止丢失 pwd 当前工作目录 cd(不加参数) 进root cd(folder) 进入文件夹 cd ...

  7. Servlet、JSP中页面跳转的方式

    一.Servlet:当然,在servlet中,一般跳转都发生在doGet, doPost等方法里面.1)  redirect 方式response.sendRedirect("success ...

  8. tomcat解决加载JSP文件过大错误

    当遇到多个Jsp include一起的时候加载时遇到如下错误: Error:SEVERE: Servlet.service() for servlet jsp threw exception org. ...

  9. Oracle索引失效问题:WHERE C1='' OR C2 IN(SubQuery),并发请求时出现大量latch: cache buffers chains等待

    问题描述: 项目反馈某功能响应时间很长,高峰期时系统整体响应很慢... 获取相应的AWR,问题确实比较严重,latch: cache buffers chains等待,因为这些会话SQL执行时间太长, ...

  10. tar 命令详解

    tar命令[root@Linux ~]# tar [-cxtzjvfpPN] 文件与目录 -C 目标目录(注:解压时)参数:-c :建立一个压缩文件的参数指令(create 的意思):-x :解开一个 ...