[No.5 jQuery源码解析—逐段解析(5)

今天,更新有点晚,

但是干货不怕晚,

接着昨天讲得讲,

把第一段讲的没讲完的继续讲解。

(function(){

        (21 , 94定义了一些变量和函数 jQuery = function(){};

        (96 , 283给JQ对象添加一些方法和属性

        (285 , 347extend : JQ的继承方法

        (349 , 817jQuery.extend() : 扩展一些工具方法

        (877 , 2856)  Sizzle : 复杂选择器的实现

        (2880 , 3042Callbacks : 回调对象 : 对函数的统一管理

        (3043 , 3183Deferred : 延迟对象 : 对异步的统一管理

        (3184 , 3295support : 功能检测

        (3308 , 3652data() : 数据缓存

        (3653 , 3797queue() : 队列方法 : 执行顺序的管理

        (3803 , 4299attr() prop() val() addClass() : 对元素属性的操作

        (4300 , 5128on() trigger() : 事件操作的相关方法

        (5140 , 6057DOM操作 : 添加 删除 获取 包装 DOM筛选

        (6058 , 6620css() : 样式的操作

        (6621 , 7854提交的数据和ajax() : ajax() load() getJSON()

        (7855 , 8584animate() : 运动的方法

        (8585 , 8792offset() : 位置和尺寸的方法

        (8804 , 8821JQ支持模块化的模式

        (8826)  window.jQuery = window.$ = jQuery;

    })();

接下来,我们看到32-35行这一块,

// Use the correct document accordingly with window argument (sandbox)

    location = window.location,

    document = window.document,

    docElem = document.documentElement,


它是把window下的一些进行变量存储,

比如location啊,documentElement啊变量存储,

就是说不存储的话,平时就可以这么去用,

我们打开压缩版本可以看到,

这里的这个i就是window.location

这样有利于版本的压缩,对压缩很有意义,

前面的locationdocument就不讲了,

这个docElemdocument

其实document就是页面节点当中的HTML标签,

就是用来存一下它,在下边都会有用的。

然后,继续看下边两句话,

    // Map over jQuery in case of overwrite

    _jQuery = window.jQuery,

    // Map over the $ in case of overwrite

    _$ = window.$,

其实这两句话的意思就是:
它是和我们防止冲突,有一定关系的,

jQuery中防止冲突就会用到这两个变量,

好,等到咱们讲到防冲突的时候,

再给大家详细讲解它俩,

现在,我先简单的说一说,

比如说我们在使用jQuery的时候,

<!-- 先引入jQuery文件 -->

<script src="jquery-2.0.3.js"></script>

<script>

    //  jQuery对外听供的接口

    // #() 和 jQuery() 这两个方法

</script>

这个$ 其实是jQuery的一个简写方式,

 尤其是这个$,在很多库当中都会使用到它,

这时候就会出现冲突,

比如说其他库中,也有一个$,比如说:

<script>

           var $ = 10;

</script>

<!-- 先引入jQuery文件 -->

<script src="jquery-2.0.3.js"></script>

这个$ 就会影响到jQuery

它有个防冲突的方法,

就是利用那两个变量才能避免,

如果说代码是这么写的话,

先走上面,再走下面吗,

走到下面的时候,

这时候的window.$存的就是10,

如果没这两个变量这会儿存的就是undefined

这会上面根本不存在这 两个东西,

跟冲突有关的,到时讲到这个方法的时候,

防冲突的方法在扩展工具方法哪里涉及到的,

到那个时候咱们再来详细地讲解。

咱们接着往下面看,

    // [[Class]] -> type pairs

     class2type = {},

这里定义了一个空的对象字面量,

我们先看它的名字,class2type这个是跟类型有关的,

这个变量在jQuery当中去使用$.type()的工具方法,

判断每个变量和元素的类型所用到的这个变量,

它最终会成为什么样的呢?咱们的类型判断,

class2type = {'[Object String]':'string','[Object Array]':'array'}

这里面会存成这样一个形式,

其实这一块都是用于类型判断的,

那到咱们讲类型判断的时候再来详细地讲解,

所以说为什么是class2type

因为这里是两个字符串格式。

我们继续看到下面,

    // List of deleted data cache ids, so we can reuse them

    core_deletedIds = [ ],


    core_version = "2.0.3",

在这里肯定跟数组有关的,

我们也能看得出来,

定义了一个空数组,

根据这个注释,我们也能看得出来,

这里是跟缓存数据有关的,

其实,这个变量里面有个deletedIds,

就是删除id的意思,

这个在之前的版本确实和删除Id有关的,

但是在这2.0.3的版本中,

这个时候,这数据存储的方法就没有用了,

改成了面向对象的写法了,

所以说用不上删除id的方式了,

所以,这咱只是知道一下就行了。

接着,咱们再来往下看,

// Save a reference to some core methods

    core_concat = core_deletedIds.concat,

    core_push = core_deletedIds.push,

    core_slice = core_deletedIds.slice,

    core_indexOf = core_deletedIds.indexOf,

    core_toString = class2type.toString,

    core_hasOwn = class2type.hasOwnProperty,

    core_trim = core_version.trim,

这里是把常用的数组啊、对象字面量啊、

字符串下面这些方法进行了局部变量的存储,

可以很方便地在后面使用,对于压缩很有帮助。

上边的之前也讲过,我们来说说最后这个,

这个trim是去掉字符串的前后空格,

在之前老版本的浏览器下这个方法是没有的,

我们只能用正则去写,才能去掉前后空格,

在高级浏览器中是有的,我们可以直接拿来用,

所以,我们简单地来看一下怎么拿来用,

// 比如,我们在这里先写个字符串

// 在前后加一些空格

// 我可以在两边加一个小括号,才能看出空格

alert('('+'   1111   '+')')

结果如下:

很明显能看出前后空格,

如果说直接在字符串内调用trim方法,

alert('('+'   1111   '.trim()+')')

结果如下:

是不是,就去掉了前后的空格,

所以在高级浏览器下,

咱们可以直接调用这个方法。

下边呢,我们看到了jQuery这个函数,

// Define a local copy of jQuery

    jQuery = function( selector, context ) {

        // The jQuery object is actually just the init constructor 'enhanced'

        return new jQuery.fn.init( selector, context, rootjQuery );

    },

前面我们总结框架结构的时候给大家说过,

这个jQuery函数就是对外提供的方法接口,

通过挂在到window上,

可以在闭包外面进行查找,

前面,我们也说过,

这个函数执行过后会返回的是对象,

返回对象的时候,

这个对象后边才能节对象所拥有的方法,

为什么这个构造函数不用其他的,

却还是用jQuery相关的,

我们看下下面的源码,

// 96行

jQuery.fn = jQuery.prototype = {

这里可以看出,fn就是jQuery的原型,

咱们先来说说普通写面向对象的方法,


// 比如,我们在这里先写个字符串

// 在前后加一些空格

// 我可以在两边加一个小括号,才能看出空格

// alert('('+'   1111   '.trim()+')')

// 先写个构造函数

     function Aaa(){


};

// 然后在这个构造函数下面添加原型

// 一般我们都会写一个初始化的方法

// 让程序调用的时候就可以执行了

    Aaa.prototype.init = function(){


};

// 然后添加下原型下的其它方法

     Aaa.prototype.css = function(){


};

// 咱们在下面new一个构造函数

// 就能创建一个出一个对应的对象

    var a1 = new Aaa();

// 创建好这个对象之后

// 有初始化方法,我们就要先初始化一下

// 这个代码就执行了

    a1.init();

// 执行过后,就能通过a1来调用css方法或其它的方法

    a1.css();

大体上,面对对象就是这样的,

但在jQuery当中没有这样,

它是这样做的,

// 比如说还是先写一个构造函数

function jQuery(){

            return new  jQuery.prototype.init();

};

jQuery.prototype.init = function(){


};

jQuery.prototype.css = function(){


};

// jQuery是这样调用的

    jQuery().css();

当调用的时候,

return后的那句话就会执行,

这句话一执行,这个函数就会执行,

这个函数一执行,就说明初始化方法就调用了,

jQuery中你这样去调用后,

就不需要初始化的步骤了,

而且直接返回的是对象,

就说明直接调用是不是就创建出来这个a1了呀,

这个对象就能拥有css的方法了,

所以说看一下jQuery

就很方便的解决了之前的这种繁琐的操作,

一目了然就能找到css

细心的小伙伴会发现,

我这里说的好像有问题,

它怎么能找到css方法的呢?

这个确实光这么去写是有问题的,

其实在jQuery当中我们可以找到这句话,

// 283行

// Give the init function the jQuery prototype for later instantiation

jQuery.fn.init.prototype = jQuery.fn;

注意这里的fn就是原型,

如果把这句话加到里面,

// 比如说还是先写一个构造函数

function jQuery(){

            return new  jQuery.prototype.init();

};

jQuery.prototype.init = function(){


};

jQuery.prototype.css = function(){


};

jQuery.fn.init.prototype = jQuery.prototype;

// jQuery是这样调用的

    jQuery().css();

这样就可以了,对吧!

因为,是把这个jQuery原型

给这个构造函数初始化下边的原型,

那就形成了一个对象的引用,

所以说把一个对象赋给另一个对象的话,

这样的话就出现了一个对象的引用的关系,

我们在后面或前面的构造函数原型上进行修改的话,

其实是一样的,对吧!

这就是jQuery中的一个设计方式。

就可以形成这样的调用方式。

下边是很多正则,

    // Used for matching numbers

    core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,

首先的这个正则的作用是去找匹配数字的,

包括正负数、带不带小数点,

而且还包括科学计数法,比如很大的一个数字,

可以通过科学计数法去表示,

这个正则会在后面使用,到时咱们再说。

    // Used for splitting on whitespace

    core_rnotwhite = /\S+/g,

这个正则是匹配单词的有关的,

去找元素没有空格分隔开的。

// A simple way to check for HTML strings

    // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)

    // Strict HTML recognition (#11290: must start with <)

    rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,

这个正则前面在或之前匹配的是一个标签,

比如,我们创建标签的时候会用到这个正则,

后面这一块是匹配id的形式,

我们可以看它的注释,

它是防止xss注入,

通过locationhash值,

我们都知道XSS是注入木马的一种方式,

比如输入框留言板有漏洞,

他可以输入一段木马程序,

你一点击就上传或者就执行了,

这时候是非常危险的,

比如我们去做hash值改变的时候,

有可能会遇到类似的问题。

    // Matches dashed string for camelizing

    rmsPrefix = /^-ms-/,

    rdashAlpha = /-([\da-z])/gi,

我们看第一个ms是什么意思,

这是IE的一个前缀,

它除了匹配字母也能匹配数字,

比如说 -2d就可以转成2d

这都是跟CSS3有关的,

这一块,我没有讲的特别详细,

如果对正则有不熟悉的,

可以看我之前发的正则的内容进行学习。


OK,咱们这段暂时讲到这里!



回看上一集:

原文中此处为链接,暂不支持采集


别走开,下集更精彩。

喜欢文章的小伙伴,

希望大家多多转发分享,

你的分享就是我的动力!

喜欢 分享 or

推荐阅读更多精彩内容