jquery原理的简单分析,让你扒开jquery的小外套。
引言
最近LZ还在消化系统原理的第三章,因此这部分内容LZ打算再沉淀一下再写。本次LZ和各位来讨论一点前端的内容,其实有关jquery,在很久之前,LZ就写过一篇简单的源码分析。只不过当时刚开始写博客,写的相对来讲比较随意,直接就把源码给贴上来了,尽管加了很多注释,但还是会略显粗糙。
这次LZ再次执笔,准备稍微规范一点的探讨一下jquery的相关内容。
jquery的外衣
jquery是一个轻量级的JS框架,这点相信大部分人都听过,而jquery之所以有这样一个称呼,就是因为它悄悄披了一件外衣,将自己给隐藏了起来。
//以下截取自jquery源码片段
(function( window, undefined ) {
/* 源码内容 */
})( window );
上面这一小段代码来自于1.9.0当中jquery的源码,它是一个无污染的JS插件的标准写法,专业名词叫闭包。可以把它简单的看做是一个函数,与普通函数不同的是,这个函数没有名字,而且会立即执行,就像下面这样,会直接弹出字符串。
(function( window, undefined ) {
alert("Hello World!");
})( window );
可以看出来这样写的直接效果,就相当于我们直接弹出一个字符串。但是不同的是,我们将里面的变量变成了局域变量,这不仅可以提高运行速度,更重要的是我们在引用jquery的JS文件时,不会因为jquery当中的变量太多,而与其它的JS框架的变量命名产生冲突。对于这一点,我们拿以下这一小段代码来说明。
var temp = "Hello World!";
(function( window, undefined ) {
var temp = "ByeBye World!";
})( window );
alert(temp);
这段代码的运行结果是Hello而不是ByeBye,也就是说闭包中的变量声明没有污染到外面的全局变量,倘若我们去掉闭包,则最终的结果会是ByeBye,就像下面这样。
var temp = "Hello World!";
// (function( window, undefined ) {
var temp = "ByeBye World!";
// })( window );
alert(temp);
由此就可以看出来,jquery的外衣就是这一层闭包,它是很重要的一个内容,是编写JS框架必须知道的知识,它可以帮助我们隐藏我们的临时变量,降低污染。
jquery的背心
刚才我们说了,jquery将自己声明的变量全部都用外衣遮盖起来了,而我们平时使用的Jquery和$,却是真真实实的全局变量,这个是从何而来,谜底就在jquery的某一行代码,一般是在文件的末尾。
window.jQuery = window.$ = jQuery;
这一句话将我们在闭包当中定义的jQuery对象导出为全局变量jQuery和$,因此我们才可以在外部直接使用jQuery和$。window是默认的JS上下文环境,因此将对象绑定到window上面,就相当于变成了传统意义上的全局变量,就像下面这一小段代码的效果一样。
var temp = "Hello World!";
(function( window, undefined ) {
var temp = "ByeBye World!";
window.temp = temp;
})( window );
alert(temp);
很明显,它的结果应该是ByeBye,而不是Hello。因为我们在闭包中导出了temp局部变量为全局变量,从而覆盖了第一行声明的全局变量temp。可以看出,就是通过导出的方式,jquery露出了自己的小背心。
jquery的内裤
内裤保护的是我们的核心器官,因此非常重要。那么jquery的内裤也一样,也是最核心的功能,就是选择器。而选择器简单理解的话,其实就是在DOM文档中,寻找一个DOM对象的工具。
首先我们进入jquery源码中,可以很容易的找到jquery对象的声明,看过以后会发现,原来我们的jquery对象就是init对象。
jQuery = function( selector, context ) {
return new jQuery.fn.init( selector, context, rootjQuery );
}
这里出现了jQuery.fn这样一个东西,它的由来可以在jquery的源码中找到,它其实代表的就是jQuery对象的原型。
jQuery.fn = jQuery.prototype;
jQuery.fn.init.prototype = jQuery.fn;
这两句话,第一句把jQuery对象的原型赋给了fn属性,第二句把jQuery对象的原型又赋给了init对象的原型。也就是说,init对象和jQuery具有相同的原型,因此我们在上面返回的init对象,就与jQuery对象有一样的属性和方法。
我们不打算深究init这个方法的逻辑以及实现,但是我们需要知道的是,jQuery其实就是将DOM对象加了一层包裹,而寻找某个或者若干个DOM对象是由sizzle选择器负责的,它的官方地址是http://sizzlejs.com/,有兴趣的猿友可以去仔细研究下这个基于CSS的选择器。
下面是LZ截取的一个jQuery对象的属性和方法截图,方法这里就不提了,对于属性来说,我们最需要关注的只有一个属性,就是[0]属性,[0]其实就是原生的DOM对象。
很多时候,我们在jQuery和DOM对象之间切换时需要用到[0]这个属性。从截图也可以看出,jQuery对象其实主要就是把原生的DOM对象存在了[0]的位置,并给它加了一系列简便的方法。这个索引0的属性我们可以从一小段代码简单的看一下它的由来,下面是init方法中的一小段对DOMElement对象作为选择器的源码。
// Handle $(DOMElement)
if ( selector.nodeType ) {
/* 可以看到,这里将DOM对象赋给了jQuery对象的[0]这个位置 */
this.context = this[0] = selector;
this.length = 1;
return this;
}
这一小段代码可以在jquery源码中找到,它是处理传入的选择参数是一个DOM对象的情况。可以看到,里面很明显的将jQuery对象索引0的位置以及context属性,都赋予了DOM对象。代码不仅说明了这一点,也同时说明了,我们使用$(DOMElement)可以将一个DOM对象转换为jQuery对象,从而通过转换获得jQuery对象的简便方法。
jquery的大腿
大腿是非常性感令男人垂涎的地方,要说jquery最性感最令我们向往的,便是它的ready方法了,千万不要告诉LZ你使用jquery却从未用过$(function(){})或者是ready方法。这里LZ不打算带各位去看jquery的实现原理,因为比较复杂,而且这里我们的主旨不是为了一点一点的剖析源码,而是简介一下jquery的实现原理。
实现类似jquery的ready方法的效果我们是可以简单做到的,它的实现原理就是,维护一个函数数组,然后不停的判断DOM是否加载完毕,倘若加载完毕就触发所有数组中的函数。遵循着这一思想,LZ拿出很久之前写的一个小例子,来给各位看一下。
(function( window, undefined ) {
var
jQuery = {
isReady:false,//文档加载是否完成的标识
readyList:[],//函数序列
//onload事件实现
ready : function(fn){
//如果是函数,加入到函数序列
if(fn && typeof fn == 'function' ){
jQuery.readyList.push(fn);
}
//文档加载完成,执行函数序列。
if(jQuery.isReady){
for(var i = 0;i < jQuery.readyList.length ;i++){
fn = jQuery.readyList[i];
jQuery.callback(fn);
}
return jQuery;
}
},
//回调
callback : function(fn){
fn.call(document,jQuery);
}
};
//导出对象
window.$ = window.jQuery = jQuery;
//判断加载是否完成
var top = false;
try {
top = window.frameElement == null && document.documentElement;
} catch(e) {}
if ( top && top.doScroll ) {
(function doScrollCheck() {
try {
top.doScroll("left");
jQuery.isReady = true;
jQuery.ready();
} catch(e) {
setTimeout( doScrollCheck, 50 );
}
})();
}
}(window));
这段代码是LZ从之前的例子摘出来的,它的实现逻辑非常简单,但是可以达到jQuery的ready方法的效果,各位有兴趣的可以加入这个JS文件测试一下效果。需要注意的是,上面没有考虑浏览器兼容性,那段判断文档加载是否完成的代码是针对IE写的,因此只能在IE下测试。
代码当中已经嵌入了简单的注释,因此LZ这里就不多做解释了,全部的源码可以在LZ的另一篇文章jquery源码分析找到,有兴趣的猿友也可以看下,那里模拟了一个非常简陋的jquery。
jquery的胳膊
我们缺了胳膊依旧可以生活,甚至可以用脚写程序,但是不得不承认,有了胳膊的我们会更加如虎添翼。而对于jquery来说,extend方法便是它的胳膊,没有它我们依然可以很好的使用jquery,但是有了它,我们会更加畅快。
这里LZ不再详细分析extend方法,有兴趣的朋友可以参考LZ很久之前的一篇文章jquery扩展函数详解,那里有较为详细的分析和解释。这里LZ只简单说两个extend方法的常用方式。
1、使用jQuery.fn.extend可以扩展jQuery对象,使用jQuery.extend可以扩展jQuery,前者类似于给类添加普通方法,后者类似于给类添加静态方法。
2、两个extend方法如果有两个object类型的参数,则会将后面的参数对象属性扩展到第一个参数对象上面,扩展时可以再添加一个boolean参数控制是否深度拷贝。
小结
本次对于jquery的简单分析就到此为止了,由于LZ并不专注于前段开发,所以对于jquery一直是采取着适可而止的研究方式。不过只要还在做Web开发,就离不开前端,因此我们也不能放弃前端。
jquery原理的简单分析,让你扒开jquery的小外套。的更多相关文章
- jQuery.buildFragment源码分析以及在构造jQuery对象的作用
这个方法在jQuery源码中比较靠后的位置出现,主要用于两处.1是构造jQuery对象的时候使用 2.是为DOM操作提供底层支持,这也就是为什么先学习它的原因.之前的随笔已经分析过jQuery的构造函 ...
- Hash算法原理的简单分析
哈希计算就是努力的把比较大的数据存放到相对较小的空间中.最常见的哈希算法是取模法.下面简单讲讲取模法的计算过程.比如:数组的长度是5.这时有一个数据是6.那么如何把这个6存放到长度只有5的数组中呢.按 ...
- jQuery核心结构简单分析
以下分析均采取沙箱模式 (function (window) { //为了提高性能把需要的变量统一提前声明 var arr = [], push = arr.push; //为区别jQuery,此文章 ...
- wp7之换肤原理简单分析
wp7之换肤原理简单分析 纠结很久...感觉勉强过得去啦.还望各位大牛指点江山 百度找到这篇参考文章http://www.cnblogs.com/sonyye/archive/2012/03/12/2 ...
- AbstractRoutingDataSource 实现动态数据源切换原理简单分析
AbstractRoutingDataSource 实现动态数据源切换原理简单分析 写在前面,项目中用到了动态数据源切换,记录一下其运行机制. 代码展示 下面列出一些关键代码,后续分析会用到 数据配置 ...
- mr原理简单分析
背景 又是一个周末一天一天的过的好快,今天的任务干啥呢,索引总结一些mr吧,因为前两天有面试问过我?我当时也是简单说了一下,毕竟现在写mr程序的应该很少很少了,废话不说了,结合官网和自己理解写起. 官 ...
- 简单分析ThreadPoolExecutor回收工作线程的原理
最近阅读了JDK线程池ThreadPoolExecutor的源码,对线程池执行任务的流程有了大体了解,实际上这个流程也十分通俗易懂,就不再赘述了,别人写的比我好多了. 不过,我倒是对线程池是如何回收工 ...
- 简单分析ucenter 会员同步登录通信原理
1.用户登录discuz,通过logging.php文件中的函数uc_user_login对post过来的数据进行验证,也就是对username和password进行验证. 2.如果验证成功,将调用位 ...
- jQuery构造函数init参数分析(二)
接着上一篇随笔讨论. 如果selector是其他字符串情况就比较多了比较复杂了 // Handle HTML strings if ( typeof selector === "string ...
随机推荐
- 解决JBoss只能通过localhost访问不能通过IP的问题
前序 现在EJB是真的有点落伍了么,网上找点资料都挺难的样子,而且都是很久的了..好吧,最近对EJB有点兴趣学习一下,结果下载到服务器启动后,居然不能直接通过服务器IP访问,也是醉了,默认只能通过本地 ...
- 跨过Django的坑
在最近的Django的学习中,慢慢的开始踩坑,开此栏,专为收纳Django的坑,在以后的学习中以便警示.(使用工具为pycharm专业版2018.2.4,python3.5.2,Django版本2.1 ...
- 推荐linux下的数据库开发工具DBeaver 开源免费
linux下不错的数据库管理工具 DBeaver 操作比较友好,基于eclipse.使用jdbc链接,链接数据库非常全(oracle mysql mssql sqlite 常见的统统支持).而且可以 ...
- 脱壳_01_虚拟机壳_VMP
写在前面的话: 上一篇文章中,带领大家一起分析了简单的压缩壳ASPACK,今天,就和大家一起来揭开VMP这道神秘的面纱: [花指令]:扰乱调试器的,并不执行: [混淆]:对原指令进行拆解或等价替换,会 ...
- 开源作业调度框架 - Quartz.NET - 实战使用2
纠正第一篇文章的一个错误代码. 下面是错误代码,这样并不能得知系统中是否已经存在该JobId //实例化一个作业Key对象,用于获取作业对象或判断是否存在作业时使用. JobKey jobKey = ...
- November 12th, 2017 Week 46th Sunday
I love you not for who you are, but for who I am with you. 我爱你不是因为你是谁,而是因为跟你在一起,我是谁. I enjoy the fee ...
- DevExpress07、DataNavigator、 ControlNavigator
https://documentation.devexpress.com/WindowsForms/DevExpress.XtraEditors.DataNavigator.class 1.DataN ...
- 《阿里巴巴 Java 开发手册》划重点!
[强制]小数类型为 decimal,禁止使用 float 和 double. 说明:float 和 double 在存储的时候,存在精度损失的问题,很可能在值的比较时,得到不 正确的结果.如果存储的数 ...
- Spark项目之电商用户行为分析大数据平台之(六)用户访问session分析模块介绍
一.对用户访问session进行分析 1.可以根据使用者指定的某些条件,筛选出指定的一些用户(有特定年龄.职业.城市): 2.对这些用户在指定日期范围内发起的session,进行聚合统计,比如,统计出 ...
- 【转】SVN branches trunk 合并 讲解
转自:http://blog.csdn.net/e3002/article/details/21469437 使用svn几年了,一直对分支和合并敬而远之,一来是因为分支的管理不该我操心,二来即使涉及到 ...