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. 开始写Effective系列总结一些前端的心得

    确实是没有时间整理以及总结和发表自己的感慨.难得中秋银行的事情搞完了自己清闲3天,是时候总结一下从大公司做.NET PC 端网站的开发到现在做移动互联网的银行及政府微信公众号的开发的感触.当时自己的选 ...

  2. 计算机网络自学之路------IP协议(1)

    1)TCP/IP模型与OSI对应 2)TCP/IP集每层主要协议 3)IP协议 4)IP地址的命名与使用 5)子网与子网掩码 1)TCP/IP模型与OSI对应关系 我们看到,TCP/IP只有四层与OS ...

  3. C#生成随机字符串(数字,字母,特殊符号)

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  4. 如何配置网络使得宿主机能够访问VM数据库?

    https://www.zhihu.com/question/23955166 背景:公司内外网区分,不能同时上,局域网内得手动切换两个网络,分别访问外网或者内网,ip是动态获取的.现在本机上装有vm ...

  5. SolrCloud分布式集群部署步骤

    Solr及SolrCloud简介 Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口.用户可以通过http请求,向搜索引擎服务器提交一定格式的XML文件,生成 ...

  6. linux下查看系统信息

    lspci:   这个工具用来查看所有连接到pci总线上的所有设备信息. 如果有些系统没有lspci,安装后即可使用,有些老死的版本中需要root权限才可使用. 一些用法: lspci    列出所有 ...

  7. winform中button的image属性无法更改

    在开发一个winform程序的时候,界面中的button的image本来有一个贴图A.后来我觉得不合适,打算换成贴图B. 但是这时问题出现了:虽然我改成了贴图B,在IDE中的预览也是贴图B,但是每次编 ...

  8. Python 各进制间的转换(转)

    转载自:http://blog.chinaunix.net/uid-21516619-id-1824975.html python 2.6以后内置函数#10进制转为2进制>>> bi ...

  9. html5之history对象 控制浏览器前进或后退事件

    一.摘要: 总结用history对象操作浏览器的历史记录的方法,在项目中使用的是mui框架,总结中包括我在实际项目中遇到的问题. 二.总结: 实现效果: 实现代码: 上面的编辑页面加载的时候就要先调用 ...

  10. 自定义 Activity 的 标题栏 TitleBar

    自定义 Activity 的 标题栏 TitleBar 1. 修改标题栏的高度,背景 编辑styles.xml,添加: <?xmlversion="1.0" encoding ...