关注:国内开源jQuery-UI组件库:Operamasks-UI

jQuery版本:v1.7.1

jQuery1.7系列一:   jQuery 对象的实质

一.何为jQuery对象

        用过jQuery的朋友都知道,jQuery很大的一个特点就在于其选择器上,我们可以很容易对众多的dom节点进行操作,而且还是链式的操作,这一切都要得益于jQuery对象,那么jQuery对象到底是什么?

        我们经常写类似这样的代码: jQuery(“div”).addClass(“myCls”),而这里jQuery(“div”)返回的结果就是jQuery对象,其实它也就是一个javascript对象来的,只是这个对象的创建过程比较复杂而已,而只有理解好了jQuery对象的实质,才能更好的深入学习jQuery。

 

二.jQuery对象创建的背后

    为了把握好jQuery对象的创建,有必要对其创建过程进行一个深入的分析。以下代码是jQuery对象创建的一个架子,我们可以由此来学习。

(function( window, undefined ) {
	var jQuery = (function() {
		var jQuery = function( selector, context ) {
			return new jQuery.fn.init( selector, context, rootjQuery );
		},
		jQuery.fn = jQuery.prototype = {
			constructor: jQuery,
			init: function(selector, context, rootjQuery){
				//做一些初始化工作,比如查找对应选择器的dom元素
			},
			length: 0
			//其它一些东西
		};
		jQuery.fn.init.prototype = jQuery.fn;
		return jQuery;
	})();
	window.jQuery = window.$ = jQuery;
})(window);

接下来,我们一步一步来解开jQuery对象的谜底。

 

1.      最外层的闭包代码是这样的:

(function( window,undefined ) {

})(window);



        把window对象传进去了,这倒没什么,有趣的是为什么会有个undefined 的形参? 在javascript语言中,Undefined是其中的一个类型,而其类型值只有 undefined 一个,就像Number也是其中的一个类型,但类型值却有多个,如100,20,88等等。而这个 undefined是用来标识一个未赋值的变量的,就比如声明一个变量 var fun , 这时fun的值就为undefined。但是由于有些古老的浏览器并不直接认识undefined,然而在调用函数传递参数时如果形参个数大于实参,后边的形参却会被赋值真正的undefined,所以像上边这种写法是最保险的,能够保证闭包的形参undefined 一定是Undefined类型的唯一值 undefined.

        如果觉得有点晕,看下边这个例子。

var a =undefined;



        在某些旧浏览器中,如果它不能直接认识undefined,那么这样写应该会报undefined 这个变量没有定义的错误,而如果这样写

(function(undefined){

    var a = undefined;

})();



那么就一定不会报错了,所以jQuery还是考虑得很周到的。

 

2.      让我们再次精简代码,看看这个jQuery到底是什么

var jQuery = (function() {

                   var jQuery = function(selector, context ) {

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

                   },

                   return jQuery;

         })();

         window.jQuery = window.$ = jQuery;

 

在使用的时候,我们是这样写的 $(“div”),而这个$其实就是下边这个函数,

var jQuery = function( selector, context ) {

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

},

 

所以执行 var $obj = $(“div”)就相当于执行

var $obj= return new jQuery.fn.init( "div", context, rootjQuery );



         到这里,我们便了然于胸,原来所谓的jQuery对象就是jQuery.fn.init这个函数的一个实例而已。

上边最原始的骨架图现在还剩下两句比较难懂的语句,它们是

jQuery.fn= jQuery.prototype = {}; //代码1

jQuery.fn.init.prototype= jQuery.fn; //代码2



为了更清晰到底发生了什么事,我们直接看执行这两句代码后结果如何:

 

 

 

 

        由以上图可以看出,这时候,init函数的prototype已经指向了jQuery.fn 所指向的对象,那也就是说,如果我向fn添加属性的话,那么 new init() 得到的实例也就相应可以找到新加的属性了,这也就是jQuery的插件机制。

         比如,你想添加一个方法,判断选择器中是否包括了表单,那么该插件大致可以这样写:

$.fn.containsForm = function(){

 var i=0,

      el;

    while(el=this[i++]){

             if(el.tagName.toLowerCase() === ‘form’){

                 return true;

             }

    }

    return false;

}

 

然后就可以直接使用该插件了,如 $(“myform”).containsForm();

 

       jQuery对象主要就是这样了,顺便还谈到了jQuery对fn的扩展机制,在jQuery的源码中,对jQuery对象添加了很多便利的方法,如addClass,find等,都是通过这种方式实现的。