jquery1.5代码分析

Jquery core解析

jquery的一般使用方式

jquery最常见的用法形如:

$(str).func1();

str可以是html或者一个选择器,$是个函数,可以把str转换成一个jquery对象。

一个jquery对象可以认为是一组dom对象的包装,jquery对象支持多种函数调用

“$”到底是个什么东西?

在jquery的源代码中,$函数就是jQuery函数,outro.js有如下申明:

window.jQuery = window.$ = jQuery;

其中jQuery的申明就在core函数里

var jQuery = (function(){
 
var jQuery = function( selector, context ) {
 
returnnew jQuery.fn.init( selector, context, rootjQuery );
 
}
 
//...return jQuery;
});

jquery的申明是放在一个闭包里的,这样可以避免变量的名字空间污染。

jquery对象是个什么东西

jquery对象是

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

生成的。

javascript里,new的操作非常关键,new做的事情可以参考相关文章,简单讲分为以下三步。

var p ={};
 
jQuery.fn.init.apply(p);
 
p.__proto__ = jQuery.fn.init.prototype;

既然jquery对象是init的new操作生成的,那么init的prototype就至关重要了,于是接下去我们就能看到:

jQuery.fn.init.prototype = jQuery.fn;
jQuery.fn = jQuery.prototype = {
constructor:jQuery,
 
init: function(selector, context, rootjQuery){
 
//....}
 
}

jQuery.fn.init的prototype是jquery.fn,这是一个普通Object,所有jquery对象调用函数时都会通过原型链查找到它,使用jquery.fn里面的方法。这里把jQuery.prototype也设置了一下,目的是使jqueryObj instanceof jQuery的结果是true。

如果调用new jQuery(str),效果和普通的jQuery调用是一样的,因为如果在构造函数中返回了一个对象,new的结果就是这个返回的对象,而不是隐含生成的那个(构造函数里的this)

init函数会根据传入的参数类型不同(一般的类型有html text、dom element、selector),做不同的处理。但最终返回的东西都是一个具有length、splice、push等属性的“假数组”对象,也就是说这个对象具有和数组类似的一些属性,但它的原型(__proto__)和Array.prototype无关,jqueryObj instanceof jQuery的结果也是true

在研究过程中,我同时发现一个有趣的现象:

从firebug中可以看到,jQuery对象是一个数组。这是为什么呢?

其实它返回的仍然是一个object,只不过这个object具有Array的所有属性,比如length、slice、splice等等,是一个”假数组”,而firebug把这个“假数组”当成了真数组显示。经过我实验,我发现firebug会把有length和splice两个属性的object认成是Array。jquery对象上还有一个toArray方法,用于把这个假数组转换成真数组。

综上所述,jquery对象是一个“假数组”,它的原型对象是jQuery.fn。

如何扩展jquery的方法

core中还可以找到extend函数的定义

jQuery.extend = jQuery.fn.extend = function() {
 
//....}

它可以往jQuery或者jQuery.fn里面插入新的对象,从而达到扩展jQuery函数库的目的。可以想见,直接往jQuery.fn里写东西,和用extend是一样的。(ps:extend还可以用来扩展普通的对象,而不仅仅是扩展jQuery和jQuery.fn)

jquery是如何实现链式调用的

链式调用是jquery一大特色,用链式调用写出的代码非常简洁,它的实现方式也体现在core中。需要实现链式调用的函数,都必须返回一个jquery对象。可以链式调用的方法有两种,一种不会改变jquery当前处理的对象,另一种会改变。

不会改表jquery对象的方法,在一系列处理完成之后会返回this,即当前处理的对象,以进行下一次的调用。

会改变jquery对象的方法,如slice、find等,需要调用pushStack方法新生成一个jquery对象,并返回新生成的jquery对象。pushStack会确保新的jquery对象会具有正确的selector属性。和老对象同样的context。老的jquery对象会保存在prevObject对象中,调用end()就会返回老的jquery对象了。

jQuery的core中还有很多常用的工具函数,会在其他部分的实现中用到,用到了再讲吧