[No.5 jQuery源码解析—逐段解析(5)
今天,更新有点晚,
但是干货不怕晚,
接着昨天讲得讲,
把第一段讲的没讲完的继续讲解。
(function(){
(21 , 94) 定义了一些变量和函数 jQuery = function(){};
(96 , 283) 给JQ对象,添加一些方法和属性
(285 , 347) extend : JQ的继承方法
(349 , 817) jQuery.extend() : 扩展一些工具方法
(877 , 2856) Sizzle : 复杂选择器的实现
(2880 , 3042) Callbacks : 回调对象 : 对函数的统一管理
(3043 , 3183) Deferred : 延迟对象 : 对异步的统一管理
(3184 , 3295) support : 功能检测
(3308 , 3652) data() : 数据缓存
(3653 , 3797) queue() : 队列方法 : 执行顺序的管理
(3803 , 4299) attr() prop() val() addClass()等 : 对元素属性的操作
(4300 , 5128) on() trigger() : 事件操作的相关方法
(5140 , 6057) DOM操作 : 添加 删除 获取 包装 DOM筛选
(6058 , 6620) css() : 样式的操作
(6621 , 7854) 提交的数据和ajax() : ajax() load() getJSON()
(7855 , 8584) animate() : 运动的方法
(8585 , 8792) offset() : 位置和尺寸的方法
(8804 , 8821) JQ支持模块化的模式
(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,
这样有利于版本的压缩,对压缩很有意义,
前面的location和document就不讲了,
这个docElem是document,
其实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注入,
通过location的hash值,
我们都知道XSS是注入木马的一种方式,
比如输入框留言板有漏洞,
他可以输入一段木马程序,
你一点击就上传或者就执行了,
这时候是非常危险的,
比如我们去做hash值改变的时候,
有可能会遇到类似的问题。
// Matches dashed string for camelizing
rmsPrefix = /^-ms-/,
rdashAlpha = /-([\da-z])/gi,
我们看第一个ms是什么意思,
这是IE的一个前缀,
它除了匹配字母也能匹配数字,
比如说 -2d就可以转成2d,
这都是跟CSS3有关的,
这一块,我没有讲的特别详细,
如果对正则有不熟悉的,
可以看我之前发的正则的内容进行学习。
OK,咱们这段暂时讲到这里!
回看上一集:
原文中此处为链接,暂不支持采集
别走开,下集更精彩。
喜欢文章的小伙伴,
希望大家多多转发分享,
你的分享就是我的动力!
喜欢 分享 or