jQuery 中对 CommonJs 的支持处理

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 函数供你使用。

时间: 2024-08-10 11:57:59

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

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

$("body").animate({"scrollTop":top}): 只被chrome支持,而不被Firefox支持 $("html").animate({"scrollTop":top}): 只被Firefox支持,而不被chrome支持. 如果想让这段js被chrome和Firefox都支持的话,应该这样: $("html,body").animate({"scrollTop"

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

jQuery中animate()的方法可以去w3school查看,这里主要说一下: $("body").animate({"scrollTop":top}) 不被Firefox支持问题的解决. 其实是使用body的: $("body").animate({"scrollTop":top}) 只被chrome支持,而不被Firefox支持. 而使用html的: $("html").animate({"

JQuery中$.ajax()方法参数详解

url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和 delete也可以使用,但仅部分浏览器支持. timeout: 要求为Number类型的参数,设置请求超时时间(毫秒).此设置将覆盖$.ajaxSetup()方法的全局设 置. async:要求为Boolean类型的参数,默认设置为true,所有请求均为异步请求. 如果需要发送同步请求,请将此选项

jQuery中$.ajax()详解(转)

JQuery中$.ajax()方法参数详解     url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. type: 要求为String类型的参数,请求方式(post或get)默认为get.注意其他http请求方法,例如put和 delete也可以使用,但仅部分浏览器支持. timeout: 要求为Number类型的参数,设置请求超时时间(毫秒).此设置将覆盖$.ajaxSetup()方法的全局设 置. async:要求为Boolean类型的参数,默认设置为true,所有

jQuery中的bind() live() delegate()之间区别分析

jQuery中的bind() live() delegate()之间区别分析 首先,你得要了解我们的事件冒泡(事件传播)的概念,我先看一张图 1.bind方式 $('a').bind('click',function (){ alert('click'); }) 解析:这种方式最简单,jq扫描文档找出所有的a,让将函数绑定到每个元素的click事件上 2.live方式 $('a').live('click',function (){ alert('click'); }) 解析:jq将函数绑定到$

jQuery中的事件和动画

一.jQuery中的事件 加载DOM 在JS中等待页面加载完成通常使用window.onload方法,而在jQuery中则使用$(document).ready()方法来替代传统的window.onload方法.这两者有很大的不同: 执行时机 window.onload方法是在网页所有的元素(包括元素关联的文件)完全加载到浏览器后才能执行.而Query中的$(document).ready()方法,在DOM载入就绪就可以对其操纵并调用它绑定的函数,此时网页中的所有元素可能并没有下载完毕. 有时我

Jquery中AJAX参数详细介绍

在使用jquery的时候,我们经常用到jquery中对ajax的封装,下面对ajax函数的各参数详细说明和讲解,以便更好的理解和使用 $.get(url, data, callback,type) 和 $.post(url, data, callback, type). 1. jQuery.ajax( options ) : 通过 HTTP 请求加载远程数据 这个是jQuery 的底层 AJAX 实现.简单易用的高层实现见 $.get, $.post 等. $.ajax() 返回其创建的 XML

JQuery中的id选择器含有特殊字符时,不能选中dom元素的解决方法

1.jquery类库在我们实际项目中用的很多,大家经常需要根据控件的id,获取对应的html元素.但是:当id含有特殊字符的时候,是不能选中的. 2.自己简单的测试了下,jquery的id选择器只支持,单词.阿拉伯数字.下划线.中划线.其中单词,包括英文字母.汉字,但是控件id属于客户不可见内容,实际中开发人员是不用汉字作为id的,这里不考虑. 3.自己写了一个工具方法,开人人员只要将id转义后,jquery就能选中了,不用再考特殊字符的问题.代码是基于jquery1.6版本. function

jQuery中的事件绑定方法

在jQuery中,事件绑定方法大致有四种:bind(),live(), delegate(),和on(). 那么在工作中应该如何选择呢?首先要了解四种方法的区别和各自的特点. 在了解这些之前,首先要知道,不管你用的是(live/ bind / delegate)之中那个方法,最终都是jQuery底层都是调用on方法来完成最终的事件绑定;.unbind(), .die(), .undelegate(),也是一样的都是通过.off()来实现的; 因此从某种角度来讲除了在书写的方便程度及习惯上挑选,不