jQuery的运行机制和设计理念分析


Posted in Javascript onApril 05, 2011

其短小精悍,使用简单方便,性能高效,能极大地提高开发效率,是开发Web应用的最佳的辅助工具之一。因此大部分开发者在抛弃Prototype而选择jQuery来进行Web开发。

一些开发人员在使用jQuery时,由于仅仅只知道jQuery文档中的使用方法,不明白jQuery的运行原理,时常会碰到许多的问题。这些问题大部分是使用不当而产生,极少数是jQuery的Bug。如果不明白其运行机理和核心源码,我们也很难写出基于jQuery类库的高性能的程序出来。

在调试基于jQuery的程序时,我们大部分时间都要跟踪进入jQuery对象分析其运行的状态,但是jQuery代码不像Ext,YUI那样中规中举,它的代码有点晦涩,难懂。也就说如果想用好jQuery,一定要清楚其源码。

jQuery的设计理念

使用jQuery之前,我们都会问jQuery是什么?jQuery是一个类库,和prototype,mootools等类库一样,为Web的 JavaScript开发提供辅助功能。那为什么要选用jQuery呢?在jQuery出现之前,Prototype,YUI都是很成熟的Js的框架,而且是各有各的特点。为什么要抛弃它们,而使用后起之秀的jQuery,它有什么优秀的特性吸引开发人员呢?

回答这个问题,我们得明白jQuery的设计理念。回忆或想象一下,我们在Web开发中是如何使用JavaScript?绝大多数时间都是采用 getElementById在Dom文档中找到DOM元素,然后取值或设定值,采用innerHTML取其内容或设定其内容,或进行事件的监听(如 click),在控制样式方面,我们会进行height,width,display等的改变,达到视觉上的效果,对于Ajax方面,也是取到数据在页面的某元素里面去添充内容。

综之,我们就是在对DOM元素在进行操作。这个元素可能是一个或是多个。这个元素可能是Document,Window或DOM元素。这样我们的任务就是二大部分,一是找DOM元素,二是对DOM元素进行操作。

对于用得熟练一点,不管是采用如getElementById这样的直接查找方式还是采用如Element.lastChild这类的间接查找方式不是很难的,对于DOM元素,DOM的操作方面也是很丰富,也不是很难使用?那么要类库做什么用呢?最难的一个问题就是浏览器的兼容的问题。所有的 JavaScript框架都要解决这一个问题,同时简化JavaScript的本身自带的操作。

Prototype可以说是开创了Js类库的先河,给我们耳目一新的感觉。它解决大部分的浏览器的兼容的问题。同时简化了原始函数名长难于记忆的经常书写出的错的问题(采用$(xx)代替getElementById),提供了Ajax的访问方式,扩展了 Array,Object,Function,Event等JavaScript原生对象。

但是这些还是不能满足开发的需要,比如在DOM树中寻找DOM元素,仅仅只能是通过元素的ID,但是我们想要更方便的查找方法,同时还希望能有一个统一的入口,不要太泛,学习曲线过高或难于使用。

jQuery就是从这里出发,把所有一切都统一在jQuery对象中。使用jQuery就是使用jQuery对象。其实jQuery开创性的工作就是如其名一样:query。它强大的查找功能令所有的框架都黯然失色。jQuery实质就是一个查询器。在查询器的基础还提供对查找到的元素进行操作的功能。这样说来jQuery就是查询和操作的统一。查询是入口,操作是结果。

jQuery在实现上也可以分成两大部分,一部分是jQuery的静态方法,也可以称作实用方法或工具方法,通过jQuery.xxx()的 jQuery命名空间直接引用。第二部分是jQuery的实例方法,通过jQuery(xx)或$(xx)来生成jQuery实例,然后通过这个实例来引用的方法。这部分的方法大多数是从采用静态方法代理来完成功能。真正的功能性的操作都在jQuery的静态方法中实现。这些功能细分起来,可以分成以下几个部分:

1、Selector,查找元素。这个查找不但包含基于CSS1~CSS3的CSS Selector功能,还包含其对直接查找或间接查找而扩展的一些功能。

2、Dom元素的属性操作。Dom元素可以看作html的标签,对于属性的操作就是对于标签的属性进行操作。这个属性操作包含增加,修改,删除,取值等。

3、Dom元素的CSS样式的操作。CSS是控制页面的显示的效果。对CSS的操作那就得包含高度,宽度,display等这些常用的CSS的功能。

4、Ajax的操作。Ajax的功能就是异步从服务器取数据然后进行相关操作。

5、Event的操作。对Event的兼容做了统一的处理。

6、动画(Fx)的操作。可以看作是CSS样式上的扩展。

jQuery对象的构建

生成或构建一个jQuery对象其实就是构建并运行一个查询器(selector)。既然是查询,肯定会查找的结果(DOM元素),之后才会有对这些结果进行操作。那么这些查找的结果存放在哪里呢?最好的地方当然是这个jQuery对象内面。查找的结果可能是一个元素,也有可以是多个元素如 (NodeSet的集合的形式)。也就是说jQuery对象内面有一个集合。这个集合存放查找到DOM元素。

但是上一小节所提到jQuery对象是所有操作的统一入口,那么它的构建就不能只局限于从DOM文档中查找到DOM元素,还有可能是从别的集合中转移过来的Dom元素,还有可能是从HTML的字符串生成的DOM元素。

在jQuery文档中提供了四种方式:jQuery(expression, [context]),jQuery(html),jQuery(elements),jQuery(callback)四种构寻jQuery对象的方式。其中jQuery可以用$代替。这四种是经常用到。其实jQuery的参数可以是任何的元素,都能构成jQuery对象。

举几个例子:

1、$($("P"))可以看出其参数可以是jQuery对象或ArrayLike的集合。

2、$()是$(document)的简写。

3、$(3)会把3放到jQuery对象中集合中。

对于如$(3)这样的其中元素(如ArrayLike集合的元素)不是DOM元素,最好不要构建jQuery对象,jQuery对象的方法都是针对于DOM对象的。不是很清楚其使用的话,很有可能会导致错误。上面讲了这么多,还是很难明白其原理的,现在从源码的角度细细分析:

通过jQuery(xxx)的调用实现没有生成对象,它的this是指向Window对象的。那么jQuery的那些实例方法是怎样继承过来的呢?看一下:

var jQuery = window.jQuery = window.$ = function(selector, context)
{ return new jQuery.fn.init(selector, context);
};
这是jQuery的总的入口,jQuery对象实际上不是通过new jQuery()而继承其prototype的中的方法。jQuery对象实际是jQuery.fn.init函数生成的对象。在里我们可以看出对于 jQuery.prototype添加一些函数集的对象的意义不大。因为我们new jQuery()是可以的,但是生成的jQuery对象在return时会被抛弃。所以最好不要用new jQuery()来构建jQuery对象。jQuery对象其实就是new jQuery.fn.init。那么jQuery.fn.init.prototype上就是挂着jQuery对象的操作方法。如

jQueryjQuery.fn.init.prototype = jQuery.fn;
有时间可能会担心在589行就实现了把jQuery.fn中的函数放到jQuery.fn.init.prototype上去,那么之后的通过 jQuery.fn.extend的方法怎么办呢?这里实际是对jQuery.fn的引用。在扩展jQuery的时候,只要把相关的函数extend到 jQuery.fn就可以了。现在我们看一下jQuery.fn.init是怎么完成工作的:

init : function(selector, context) { 
selectorselector = selector || document;// 确定selector存在 // 第一种情况 Handle $(DOMElement)单个Dom 元素,忽略上下文 
if (selector.nodeType) { 
this[0] = selector; 
this.length = 1; 
return this; 
} 
if (typeof selector == "string") {//selector为string 
var match = quickExpr.exec(selector); 
if (match && (match[1] || !context)) { 
if (match[1])// 第二种情况处理$(html) -> $(array) 
selector = jQuery.clean([match[1]], context); 
else {// 第三种情况:HANDLE: $("#id")//处理$("#id") 
var elem = document.getElementById(match[3]); 
if (elem) { 
// IE会返回name=id的元素 ,如果是这样,就document.find(s) 
if (elem.id != match[3]) 
return jQuery().find(selector); 
// 构建一个新的jQuery(elem) 
return jQuery(elem); 
} 
selector = []; 
} 
} else 
// 第四种情况:处理$(expr, [context])==$(content).find(expr) 
return jQuery(context).find(selector); 
} else if (jQuery.isFunction(selector)) // 第五种情况:处理$(function)七Shortcut for document ready 
return jQuery(document)[jQuery.fn.ready ? "ready" : "load"](selector); 
// 第六种情况:处理$(elements) 
return this.setArray(jQuery.makeArray(selector)); 
}
Javascript 相关文章推荐
JavaScipt基本教程之JavaScript语言的基础
Jan 16 Javascript
checkbox 多选框 联动实现代码
Oct 22 Javascript
Javascript面向对象编程
Mar 18 Javascript
如何使用Jquery获取Form表单中被选中的radio值
Aug 09 Javascript
jQuery中parents()和parent()的区别分析
Oct 28 Javascript
JS+CSS实现鼠标滑过时动态翻滚的导航条效果
Sep 24 Javascript
跟我学习javascript的函数和函数表达式
Nov 16 Javascript
Node.js模块封装及使用方法
Mar 06 Javascript
Vuejs第十一篇组件之slot内容分发实例详解
Sep 09 Javascript
vue一步步实现alert功能
Jul 05 Javascript
AngularJs返回前一页面时刷新一次前面页面的方法
Oct 09 Javascript
vscode vue 文件模板的配置方法
Jul 23 Javascript
jQuery JSON的解析方式分享
Apr 05 #Javascript
jQuery 1.5 源码解读 面向中高阶JSER
Apr 05 #Javascript
基于jquery的动态创建表格的插件
Apr 05 #Javascript
基于jquery的合并table相同单元格的插件(精简版)
Apr 05 #Javascript
新鲜出炉的js tips提示效果
Apr 03 #Javascript
使用Firebug对js进行断点调试的图文方法
Apr 02 #Javascript
dreamweaver 安装Jquery智能提示
Apr 02 #Javascript
You might like
使用PHP获取当前url路径的函数以及服务器变量
2013/06/29 PHP
PHP中HTML标签过滤技巧
2014/01/07 PHP
WordPress中用于获取文章信息以及分类链接的函数用法
2015/12/18 PHP
thinkphp框架无限级栏目的排序功能实现方法示例
2020/03/29 PHP
JQuery 绑定事件时传递参数的实现方法
2009/10/13 Javascript
juqery 学习之五 文档处理 包裹、替换、删除、复制
2011/02/11 Javascript
Ext.get() 和 Ext.query()组合使用实现最灵活的取元素方式
2011/09/26 Javascript
求数组最大最小值方法适用于任何数组
2013/08/16 Javascript
使用js实现数据格式化
2014/12/03 Javascript
有关json_decode乱码及NULL的问题
2015/10/13 Javascript
Nodejs如何搭建Web服务器
2016/03/28 NodeJs
详解XMLHttpRequest(二)响应属性、二进制数据、监测上传下载进度
2016/09/14 Javascript
vue生成token并保存到本地存储中
2018/07/17 Javascript
微信小程序动态添加view组件的实例代码
2019/05/23 Javascript
JavaScript实现的联动菜单特效示例
2019/07/08 Javascript
浅谈layer的Icon样式以及一些常用的layer窗口使用方法
2019/09/11 Javascript
js+cavans实现图片滑块验证
2020/09/29 Javascript
[20:21]《一刀刀一天》第十六期:TI国际邀请赛正式打响,总奖金超过550万
2014/05/23 DOTA
python基础教程之数字处理(math)模块详解
2014/03/25 Python
Python3字符串学习教程
2015/08/20 Python
Python中字典和集合学习小结
2017/07/07 Python
Python3.4实现从HTTP代理网站批量获取代理并筛选的方法示例
2017/09/26 Python
python+numpy按行求一个二维数组的最大值方法
2019/07/09 Python
Python实现微信翻译机器人的方法
2019/08/13 Python
python双端队列原理、实现与使用方法分析
2019/11/27 Python
python解析xml文件方式(解析、更新、写入)
2020/03/05 Python
python中查看.db文件中表格的名字及表格中的字段操作
2020/07/07 Python
Python 合并拼接字符串的方法
2020/07/28 Python
德国大型的家具商店:Pharao24.de
2016/10/02 全球购物
德国亚洲食品网上商店:asiafoodland.de
2019/12/28 全球购物
汽车专业大学生职业生涯规划范文
2014/01/07 职场文书
教师演讲稿开场白
2014/08/25 职场文书
党员群众路线学习心得体会
2014/11/04 职场文书
2016春季幼儿园小班开学寄语
2015/12/03 职场文书
确保减税降费落地生根,用实实在在措施
2019/07/19 职场文书
诺贝尔奖获得者名言100句:句句启人心智,值永久收藏
2019/08/09 职场文书