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. Repeater 根据某一列的值加颜色

    //排队中 protected void rptOrdersList_ItemDataBound(object sender, System.Web.UI.WebControls.RepeaterIt ...

  2. DrawableLayout

    提供一个在窗口顶层显示,可从窗口边缘拖出的container组件. DrawableLayout本身作为整个容器,先进行默认显示内容的布局,再进行拖出菜单的内容布局.也就是一个DL包含两个或三个子控件 ...

  3. POJ 1321 DFS

    题意:POJ少见的中文题,福利啊. 思路: 一开始也没有思路呃呃呃 . 裸搜,连样例都过不去...参照了网上的题解:一行一行DFS 茅塞顿开啊. #include <cstdio> #in ...

  4. code标签和pre标签

    code标签: 1.code标签的定义: <code>标签, 用于表示计算机源代码或者其他机器可以阅读的文本内容.软件代码的编写者习惯了编写代码时的代码格式,那么这个<code> ...

  5. Github账户注册的过程

    首先我通过冯老师的博客园帖子中的链接进入了注册地址,填写了用户名,邮箱,和密码.然后我进入我的邮箱验证了Github网站给我发送的验证信息,至此,我的GITHUB账户便注册完成了.

  6. linux创建静态库

    [1]新建源程序staticlib.c /************************************************************************* > ...

  7. mysql配置命令 CHARACTER_SET_%字符集设置

    参照: http://blog.csdn.net/mzlqh/article/details/7621307点击打开链接 其实现在的ubuntu12. 直接sudo apt-get install M ...

  8. java标准-密码用数组比用字符串安全

    转载:http://my.oschina.net/jasonultimate/blog/166968 1) Since Strings are immutable in Java if you sto ...

  9. java中的集合类(Collection)中的Set

    set集合不包含重复元素及与我们无关的排序!我说hibernate实体类中的集合都用Set呢,难道是因为这个?

  10. 在Visual Studio中设置多核并行编译

    VS是一款非常强大实用的IDE,是在Windows环境下学习编程的首选软件. 有些时候大一点的工程项目编译要耗时挺长时间,随便修改一下代码就可能要编译将近一分钟,甚至更多.即便在开启的增量编译的情况下 ...