问答形式阅读jQuery源码(一)

笔者阅读了园友艾伦 Aaron的系列博客《jQuery源码分析系列》,主要是阅读的jQuery的原理,然后跑园友的代码,真正对jQuery源码的阅读并不多。主要是直接阅读jQuery源码,一次能读懂的部分并不多,不如先阅读源码解析的文章,然后再阅读收获更大。笔者在阅读完园友艾伦的全部jQuery源码博客之后,准备真正开始阅读jQuery的源代码。而阅读的形式属于自问自答,把在阅读博客时候的留下来的疑问提出来,再通过自己阅读源码的形式对其解答;当然也包括在阅读源代码的时候那些读不懂的地方,提出疑问,然后在慢慢消化解答。

这个jQuery源码系列并非教程,而是笔者的学习jQuery源码的笔记,因此才会采取问答这种不系统的形式。如果大家想系统学习jQuery源码,还是请仔细阅读艾伦 Aaron的博客;或是直接阅读jQuery在gitbub上的源码(目前的master版本是version to 3.1.1-pre.,笔者阅读的也是这个版本的代码)。如果在阅读后也和笔者一样,对一些内容存在疑问,可以看看笔者的系列博客,看看你有没有你疑惑的问题。

提问:如何构建jQuery的源码

在我开始阅读jQuery的源码时,发现源代码本身是有模块化的,而艾伦 Aaron阅读的版本没有,他是直接阅读的dist后的代码。那么jQuery是如何构建源代码的呢?

答:阅读jQuery在github上的README.md文件,里面已经说得非常清楚了。先安装git客户端和nodejs及npm。然后将github上的资源克隆到本地,找一个目录,然后打开命令行,输入git的clone命令:

git clone git://github.com/jquery/jquery.git

本地就会克隆出jQuery的源代码:

然后进入该目录下,在命令行上运行如下命令,jQuery就会自动安装npm模块,并构建jQuery了。

npm run build

最后在dist目录中,会构建出我们想要的jQuery文件了。

提问:git上的jQuery目录结构是怎样的

答:具体目录结构可以看上图,这里逐个介绍一下各个目录和文件的作用:

.github git相关目录
build 构建相关的脚本文件,笔者大概阅读了一下,主要是创建两个Grunt任务,负责构建(bulid)和输出(dist)
dist 输出构建后的文件,主要是jquery.js和jquery.min.js,以及jquery.min.map。这些就是我们最终使用的js文件了
external 放依赖的第三方代码,jQuery中最重的第三方库sizzle就在这里
node_modules nodejs的模块文件,构建时候安装的node非全局模块都放在这里,属性nodejs的小伙伴应该很清楚了
src jQuery自身的源代码的目录,这就是我们主要阅读的部分
test 单元测试用例
.babelrc Babel的配置文件
.editorconfig editorconfig的配置文件,editorconfig是帮助开发者在不同的编辑器和IDE之间定义和维护一致的代码风格的配置,很多ide都支持editorconfig的插件,使用这个就可以使各种ide下都能自动将代码显示成editorconfig约定的格式
.eslintignore eslint相关文件,配置不用于eslint语法检测的文件目录
.eslintrc.json eslint的配置文件。eslint和jshint比较像,可以认为是jshint的升级版,都是用来做语法检测的。
.gitattributes git相关文件,用于设置文件的对比方式
.gitignore git的配置文件,配置用于配置不需要加入版本管理的文件
.mailmap 貌似是一个邮件地址列表
.npmignore npm相关文件,配置哪些文件不需要被发布到npmjs.org
.npmrc npm的配置文件
.travis.yml Tarvis-CI的配置文件,持续集成用的,github整合了持续集成服务travis,每一次push之后,travis就会定时执行“npm test”来测试项目
AUTHORS.txt 贡献者名录
CONTRIBUTING.md 贡献代码指引
Gruntfile.js Grunt的配置文件
LICENSE.txt 授权协议
README.md github项目的说明文档
package.json npm的包文件

几个地方值得注意一下:

1.jQuery是用RequireJs做模块化工具的,所以jQuery的源代码是用AMD规范。AMD这个模块化规范主要活跃于基于浏览器的js模块管理,他有着异步加载、依赖前置等非常好的特性,当然用来做后端的代码模块管理也可以,但是笔者终究认为这里用AMD有点“大材小用”了。jQuery用AMD规范做模块化管理,可能是历史原因的影响,早些年模块化工具不像如今这么成熟。

2.jQuery是用Grunt构建的,jQuery自己做了构建的Grunt任务,具体代码可以参考build目录下的Grunt任务和Grunt的配置文件Gruntfile.js。基于Grunt,jQuery完成测试、构建、合并代码、压缩等工作,最终把构建好的文件拷贝到dist目录里面。

3.jQuery配置了npm包相关的配置,说明jQuery本身也被发布到了npmjs.org上,我们可以直接用npm安装jQuery。

4.jQuery有Babel的配置文件,那源代码是不是用ES6的语法呢?

提问:jQuery有Babel的配置文件,难道jQuery的源代码使用了ES6的语法?

答:答案是没有的,我们先不看Babel在Grunt里面的配置,直接试一下能不能在源代码中使用ES6。

先将源代码里面添加一条ES6的语法,然后执行构建。这时我们会发现构建的时候会报错,而且构建好的jQuery.js文件中ES6的语法也没有被转换为ES5的语法。这说明构建源代码的时候并没有启用Babel。

我们在来看Babel在Grunt里面的配置

babel: {
    options: {
        sourceMap: "inline",
        retainLines: true
    },
    nodeSmokeTests: {
        files: {
            "test/node_smoke_tests/lib/ensure_iterability.js":
            "test/node_smoke_tests/lib/ensure_iterability_es6.js"
        }
    }
},

可以看出,Babel仅是将测试用例中的冒烟测试用例做了转换,而源代码则不在被转换列表中。

提问:jQuery的源代码用的是AMD规范做模块化,为什么最终构建好的代码却没有AMD的语句呢?

答:阅读jQuery的源代码,我们可以很清楚的看到AMD规范的语句。

然后在dist里面的构建好的文件中,我们却找不到AMD规范语句的影子,jQuery是如何去掉了这些AMD语句呢?起初笔者认为是用了一些Grunt上的插件,后来阅读了build里面的代码才发现,是在build里面使用正则将AMD语句去除。jQuery虽然是用的AMD做模块化,但是具体的代码结构还是有自己的一套策略,这个应该就是为了最后构建代码而考虑的。

src的根目录下,共有20多个js文件,很多js文件都有同名的目录与之对应。目录之中最特别的目录就是var目录,因为var目录并不存在与之对应的名为var.js的文件。

var这个名字和js的关键字var相同,这和这个目录这样命名肯定是有关系的。没错,jQuery在去除AMD语句的时候,发现如果是var目录里的文件的话,就会将其转换为“var 文件名 = AMD输出的对象”的形式。如下图:

define( ‘var/arr‘,[],function() {
    "use strict";

    return [];
} );

define( ‘var/document‘,[],function() {
    "use strict";

    return window.document;
} );

define( ‘var/getProto‘,[],function() {
    "use strict";

    return Object.getPrototypeOf;
} );

......

源代码的这几个模块最终会把构建为:

var arr = [];
var document = window.document;
var getProto = Object.getPrototypeOf;......

而对于非“var”目录下的模块,jQuery会将define关键字等AMD相关的语句直接移除。其中sizzle模块更为特殊,jQuery在构建的时候还做了更多的操作,这里就不再细究了。

分析到这大家也能看出,jQuery这样构建是会破坏AMD各个模块的作用域的。我们之所以需要模块化我们的代码,一点是不希望我们把我们的内部(私有)变量声明到全局作用域中,而JavaScript是一种函数级作用域的语言,jQuery在构建的时候去掉了AMD的函数形式,这样所有模块的代码构建后的都会在同一个作用域里,所以在修改jQuery源代码的时候一定要小心,不要在作用域里面随意创建相同名称的变量,防止造成模块间的冲突。

以上就是jQuery去除AMD的过程。

了解了jQuery的构建过程后,我们就可以轻松愉快地浏览jQuery的源代码了。事实上如果jQuery构建的时候采用webpack这样的工具就简单多了。jQuery没有采用这样的工具可能也是历史原因,或者是出于进一步优化代码的目的。

时间: 2024-12-22 00:27:56

问答形式阅读jQuery源码(一)的相关文章

问答形式阅读jQuery源码(二)

这一篇笔者主要以设计的角度探索jQuery的源代码,很多人说jQuery设计过于个人主义话,其实这样说是有一定偏见的,因为好的设计是可通用的.共通的,jQuery这么好用,我们怎么能说他的设计是个人主义呢?好了开始正题. 提问:jQuery是怎么暴露自己的api的? 任何框架其实都是个门面模式,外部与框架的通信必须通过一个统一的门面,而这个门面就是我们说所的api.因此学习任何框架的源码,我们都要弄清两件事: 1.哪些是私有方法,因为私有方法是框架自己内部使用,是他不希望暴露给外围用户的,这些方

问答形式阅读jQuery源码(三)

通过艾伦的博客,我们能看出,jQuery的promise和其他回调都是通过jQuery.Callbacks实现的.所以我们一起简单看看jQuery.Deferred和jQuery.Callbacks.来看看关于他们的一些提问. 提问:jQuery.Callbacks的配置为什么是用字符串参数? jQuery.Callbacks有四种配置,分别是once.memory.unique.stopOnFalse.而jQuery.Callbacks的配置形式却和以往我们熟悉的不同,不是使用json,而是使

阅读jQuery源码的18个惊喜

注释:本文使用$.fn.method指代调用一系列选中的元素的方法.例如,$.fn.addClass,指代$('div').addClass(‘blue’) 或 $('a.active’).addClass(‘in-use’)这些用法.$.fn指代jQuery对象. 1.Sizzle’s weight:Sizzle 是jQuery基于CSS选择器的DOM查找引擎.它可以将$(‘div.active’)转换成一个可操作的元素数组.Sizzle是jQuery很大的一个组成部分,但是它的规模之大的确令

阅读jquery源码与js依赖加载的模块化!

阅读源码肯定是先下载有注释的源码 我也是醉了,10309 行代码,在陆续续的一个月之内,看完了,虽有收获但收获不大, 直到又一次看jquery的github,怎么会有cmd????没听过使用jquery时候还要用requresjs啊,这是咋回事啊,jquery不是一个独立的js库么, 不过看着 src文件夹下的目录,倒是非常清晰,每个文件里面的文件代码也不多,研究 代码也容易了 然后看了下grunt 配置文件才明白, 原来jq的作者为了在开发的时候,分清楚jq的内部结构,用amd的方式进行模块化

阅读 jQuery 源码的18个惊喜

我热爱 jQuery,且尽管我认为自己算是一名高级 JavaScript 开发者,我从来没有试过由头到尾把 jQuery 的源码看一遍,直到现在.这里分享一些我一路下来学到的东西: 注意:我使用 $.fn.method() 语法来表示调用一组匹配元素的方法.比如当我说 $.fn.addClass,则表示$('div').addClass('blue') 或者 $('a.active').addClass('in-use') 此类的用法.$.fn 是 jQuery 包装元素的原型. 1. Sizz

jQuery 源码解析一:jQuery 类库整体架构设计解析

如果是做 web 的话,相信都非要对 Dom 进行增删查改,那这相信大家都或多或少接触到过 jQuery 类库,其最大特色就是强大的选择器,让开发者脱离原生 JS 一大堆 getElementById.getElementsByName...官方提供超长方法 api . jQuery 整体源码,本人也还在阅读中,暂时记录一下.(为什么要看源码,原因很简单---- 一 好好了解一下 jQuery 原理  二 为了装逼显摆).   一  使用 jQuery 时候,首先需引入 jQuery 文件,而之

jQuery源码逐行分析学习02(第一部分:jQuery的一些变量和函数)

第一次尝试使用Office Word,方便程度大大超过网页在线编辑,不过初次使用,一些内容不甚熟悉,望各位大神见谅~ 在上次的文章中,把整个jQuery的结构进行了梳理,得到了整个jQuery的简化结构,如下: 1 (function(){ 2 (21 , 94) 定义了一些变量和函数 jQuery = function(){}; 3 (96 , 283) 给JQ对象,添加一些方法和属性 4 (285 , 347) extend : JQ的继承方法 5 (349 , 817) jQuery.ex

jQuery源码分析系列(33) : AJAX中的前置过滤器和请求分发器

jQuery1.5以后,AJAX模块提供了三个新的方法用于管理.扩展AJAX请求,分别是: 1.前置过滤器 jQuery. ajaxPrefilter 2.请求分发器 jQuery. ajaxTransport, 3.类型转换器 ajaxConvert 源码结构: jQuery.extend({ /** * 前置过滤器 * @type {[type]} */ ajaxPrefilter: addToPrefiltersOrTransports(prefilters), /** * 请求分发器 *

Jquery源码分析

1.概述 jQuery是一个非常优秀的Js库,与prototype,YUI,Mootools等众多的Js类库相比,它剑走偏锋,从web开发最实用的角度出发,抛除了一些中看但不实用的东西,为开发者提供一个短小精悍的类库.由于其个短小精悍,使用简单方便,性能相对高效.众多的开发者都选择Jquery来进行辅助的web开发. 在使用jquery时开发,我们也会时常碰到许多的问题,但是jquery的代码很晦涩,难起看懂,当开发时出现了问题,看不懂源码,不知道如何去排错. John Resig,Jquery