`
jljlpch
  • 浏览: 319775 次
  • 性别: Icon_minigender_1
  • 来自: 南昌
社区版块
存档分类
最新评论

jquery对象的数组特性

阅读更多
2.3、jquery对象的数组特性
从上面一小节可以看出jquery构建函数完成了查找或转换或其它的功能,其结果就是找到元素,查找,转找不过是方式而已。找到元素就得找个地方去存储起来。这个地方是就是这一节要分析的。
存储有序数据的地方(集合)在JS中最好的当然是数组。那么又如何在jQuery内面实现数组呢?可以采用如下的方式:
jQuery.fn.prototype=new Array();
在上一节中的this.setArray(arr)函数中加上
  Array.apply(this,arr);
如果还要完美一点,就加上:
jQuery.fn.prototype.constructor=jQuery。
这样我们继承了数组的所有特性,又可以在Jquery对象进行数组的功能扩展。但是jQuery并没有这样采用继承Array而实现这个内部的集合。它采用了Array-Like的对象的实现(见JavaScript: The Definitive Guide, 5th Edition7.8节)。
类数组的对象还是对象,只不过像数组。数组与对象其实是没有什么好大的区别的,有序和无序的集合是它们区别。这个区别反应在数组有的length属性。当添加元素它会自动加上相对的个数,当删除元素,它会自动减去相对的个数。
看一下jQuery是怎么实现的:
// 第一种情况 Handle $(DOMElement)单个Dom 元素,忽略上下文
		if (selector.nodeType) {                                            ②
			this[0] = selector;
			this.length = 1;
			return this;
		}		
这是它的第一种实现方法,通过this[0]来直接设定第一个位置的Dom元素,同时设定length=1。这里我们可以看出对象与数组一样都是采用key/Value对的形式存在对象中。上面的Json形式为{0:aDom,length=1}。这里细细分析一下数组,数组是继承于对象。其[]的解释分析最终结果可以看作{}构的对象,对[]或数组的构建时会进行把index(如0.1,….)做为对象属性的key。把数组中的值做为其对应的value。同时改变length的值。这也就是说为什么本质上对象与数组没有多大的区别。在很多的源码中,如YUI中都采用对象的形式来构建多维数组。
this.setArray(jQuery.makeArray(selector));
是其第二种实现的方法,上面实现是单个的元素,这个实现的多个元素的集合。它首先调用了jQuery.makeArray(selector)这个静态方法把集合(类数组)转换成数组。
上面已经分析了数组和对象都可以采用obj.[attr]的形式来取得其key对应的value。对于集合或类数组,必须要求其实现length属性,有了length的长度,那么就从0~length-1的key属性中取得对应的value就可以了:
//把类数组的集合转换成数组,如果是单个元素就生成单个元素的数组。
makeArray: function( array ) {
	var ret = [];
	if( array != null ){	var i = array.length;
	//单个元素,但window, string、 function有 'length'的属性,加其它的判断
	  if( i == null || array.split || array.setInterval || array.call )
	  	  ret[0] = array;
	  else//类数组的集合
		  while( i )	ret[--i] = array[i];//Clone数组
	 }
return ret;
	},
生成了一个标准的数组,那么接下来setArray来干什么呢?
// 把array-like对象的元素全部push当前jquery对象。
	setArray : function(elems) {
		this.length = 0;//初始化长度,因为push会在原始的length++
		Array.prototype.push.apply(this, elems);
		return this;
	},
这个调用了Array.prototype.push来自动修改length的属性值(当然是加入了元素)。由此可以推想到Array中众多的方法(如shift)都可以看作改变length的值在对象的key/value对中完成无序到有序或重新排序的工作。实际上Array等是采用C或C++来实现的。但是它构出的JS特性让我们可以这样去思考采用JavaScript的实现方式。
上面的setArray(elems)函数只是会改变当前jQuery对象的集合,它会清除这个对象集合中以前的元素。但是有的时候我们想保存原来的集合中元素,同时也能就新传入的元素进行jquery对象的操作。它提供了pushStack函数来新建一个jQuery对象同时保存原来对象的引用。这样就可能在需要时用到自己所要的对象:
	pushStack : function(elems) {// 采用jQuery构建新对象,同时引用老对象。
		var ret = jQuery(elems);// 构建新的jquery对象
		ret.prevObject = this;// 保存老的对象的引用
		return ret;
	},
返回的是新构建成的对象,有着jQuery对象的全部功能,同时还可以通过prevObject来访问原来的老对象。

构建了类数组,那么还得提供一些方法来操作这个集合,对于集合的操作无非就是定位元素,查找元素,复制(slice)和删除的操作(splice)等。jQuery还提供each,map的扩展。
这些方法只和集合相关,与集合的元素的无关。jQuery提供了众多的和其中元素(DOM元素)相关的方法。

它提供了两个get元素的方法,get(index)和eq(index),不同是get取得是集合中的元素,而eq则是返回该元素的Clone。不会修改数组。其实可以直接通过[i]来代替get(i)。如果get没有参数则是获得全部元素。
// 取到本jquery对象的第几个Dom元素,无参数,代表全部的Dom元素
	get : function(num) {
		return num == undefined ? jQuery.makeArray(this) : this[num];
	},
// 获取第N个元素 。这个元素的位置是从0算起。
	eq : function(i) {
		return this.slice(i, +i + 1);
	},
这两个函数就不用分析了。接下来看看如何实现在集合中定位元素:
/ 找到elem在本jquery对象的位置(index)
	index : function(elem) {
		var ret = -1;
		return jQuery.inArray( // 如是jQuery对象就取第一个元素
				elem && elem.jquery ? elem[0] : elem, this);
	},

// 判断elem元素在array中的位置(index) 静态方法
	inArray : function(elem, array) {
			for (var i = 0, length = array.length;i < length; i++)
				// Use === because on IE, window == document
				if (array[i] === elem)
					return i;
			return -1;
		},
inArray是jQuery的静态方法,而index是通过调用inArray来实现其定位的功能。Index的函数支持的参数可以是jQuery对象或Dom元素,而inArray则是实用方法,支持任何的元素。

Jquery提供了如数组中slice复制的功能的方法,还提供类似concat的静态方法merge。Slice是通过Array中slice来实现的:
  / 代理数组的slice,同样的操作。
	slice : function() {
		return this.pushStack(Array.prototype.slice.apply(this, arguments));
	},
它返回生成新的jQuery对象。这个对象的集合就是要复制后的集合。对于merge,它是静态方法,实现把第二个元素追加到第一个参数的数组中。
// 把second 元素追加到first的数组中。
		merge : function(first, second) {
	 // We have to loop this way because IE & Opera overwrite the length
	 // expando of getElementsByTagName
		var i = 0, elem, pos = first.length;
		// Also, we need to make sure that the correct elements are being
		// returned (IE returns comment nodes in a '*' query)
			if (jQuery.browser.msie) {
				while (elem = second[i++])
					if (elem.nodeType != 8)
						first[pos++] = elem;

			} else
				while (elem = second[i++])
					first[pos++] = elem;

			return first;
		},
Jquery的each是对集合中每个元素都执行回调函数。
	// 当前jquery对象中每个元素都执行callback(index,elem)函数
	each : function(callback, args) {// 返回this
	// 其调用了jQuery的静态方法。prototype中的mothodize是解决这类问题的好方法
		return jQuery.each(this, callback, args);
	},	
它通过调用jQuery.each这个静态方法来完成功能的:
// 对object中的每个对象都执行callback函数进行处理。args仅仅内部用
	 each : function(object, callback, args) {
			var name, i = 0, length = object.length;
			// 和else的处理差不多,args的传参代替object的属性值
			if (args) {
				if (length == undefined) {
					for (name in object)
						if (callback.apply(object[name], args) === false)
							break;
				} else
					for (;i < length;)
						if (callback.apply(object[i++], args) === false)
							break;
	     	} else {
		       // 不是array-like的object,对每个属性进行callback函数的调用
	if (length == undefined) {
	           	for (name in object)
if (callback.call(object[name], name, object[name]) === false)
						break;
				   } else
					// array-like object,采用数组的形式来处理
	 for (var value = object[0];i < length	&& callback.call(value, i, value) !== false; value = object[++i]) {}
			}
			return object;
		},
该静态方法支持第一个参数的类数组(数组)或对象。是数组就对每个元素进行callback的操作。如果是对象,就是对每个属性值进行callback的操作。这个callback回调函数的格式如下:callback:function(index,value)。Index是索引号,value是数组的index对应的元素或对象的第index个处理的属性。如果使用args参数,那callback回调函数的格式如下:callback:function(args)。Args是给回调函数设定参数。再看一下jQuery对象的each。它的第二个参数args就是采用传入的args直接进行给callback设定参数,而不是默认提集合中index和对应的元素,但执行的次数还是集合的length次。

Jquery的map是将一组元素转换成其他数组(通过回调函数返回值组成的)	// 将一组元素转换成其他数组	然后根据这个数组构建新的jquery对象。。
	map : function(callback) {
		return this.pushStack(jQuery.map(this, function(elem, i) {
			return callback.call(elem, i, elem);
		}));
	},
这个函数首先通过jQuery.map(this, function(elem, i){}来把this的jQuery对象集合的每个元素当作回调函数的elem的参数传到回调函数中。而这个回调函数又执行实例方法的map : function(callback)中callback函数,也就是jQuery.map中的回调仅仅是传参代理的功能。jQuery.map通过代理的回调来取得转换而成的元素集合。
接下来就是采用pushStack把这集合的元素构建成新的jQuery对象并返回,同时保存原jQuery对象的引用。
看下Map的静态方法:
    // 返回对elems每个元素都进行操作的callback函数的返回值的集合。
		map : function(elems, callback) {
			var ret = [];			
			for (var i = 0, length = elems.length;i < length; i++) {
				var value = callback(elems[i], i);
				if (value != null)//说明转换的集合的个数可能少于原来的集合
					ret[ret.length] = value;
			}
			return ret.concat.apply([], ret);//采用array的concat实现
		}
Map的静态方法返回每个callback返回的元素组成的数组。

 

分享到:
评论
3 楼 haiyupeter 2012-05-07  
不过说实在的,其实jQuery不是这样就形成类数组对象的,还需要一个,请查看:http://stackoverflow.com/questions/6599071/array-like-objects-in-javascript 或者:http://haiyupeter.iteye.com/admin/blogs/1513403
2 楼 haiyupeter 2012-05-06  
非常牛逼,非常仔细,正是想要找的资料,自己看了半天没看懂jQuery是怎么样模拟数组的,向高人学习了。
1 楼 ybbkd2 2010-02-08  
没看懂...

相关推荐

    jQuery对象与DOM对象之间的相互转换

    1、jQuery对象是一个类似数组的对象,可以通过[index]的方法得到相应的DOM对象: 代码如下:  var $cr=$(“#cr”) //jQuery对象  var cr=$cr[0] //DOM对象 2、另一种是jQuery本身提供的,通过get(index)方法...

    jQuery教程学习

    第三十一节:jQuery速成- 数组和对象的操作 第三十二节:jQuery速成- 工具杂项 第八章:高级篇 - Ajax异步请求及调用实战 第三十三节:jQuery速成- Ajax请求 (讲解篇) 第三十四节:jQuery速成- Ajax请求 (实战篇)

    jQuery权威指南-源代码

    书名:jQuery权威指南(系统介绍jQuery方方面面,囊括118个实例和2个综合案例,实战性强) 作者:陶国荣 著 ...10.8.2 DOM对象与jQuery对象的类型转换/335 10.9 本章小结/337 第11章 综合案例开发...

    jquery插件使用方法大全

    使一个Dom对象成为一个Jquery对象很简单,通过下面一些方式(只是一部分): 代码 var a = $("#cid"); var b = $("&lt;p&gt;hello&lt;/p&gt;"); var c = document.createElement("table"); var tb = $(c); 编辑本段代替body...

    jQuery 1.4.1 中文参考

    11.2 数组和对象操作 183 11.2.1 jQuery.each(object, [callback]) 183 11.2.2 jQuery.extend([deep], target, object1, [objectN]) 183 11.2.3 jQuery.grep(array, callback, [invert]) 185 11.2.4 jQuery.make...

    filereader:filereader,一个用于读取本地文件的 jQuery 扩展

    type="file"] 元素已更改)返回一个 File 对象数组$.fileReader() 返回一个 jQuery 对象(一个 FileReader 实例的包装器) 创建后,此实例公开: 特性: $fileReader.file:对正在读取的 File 实例的引用。...

    韩顺平PHP JS JQUERY 所有视频下载种子 货真价实

    10-26 4 jquery对象集合遍历的四种形式及练习题讲解 jquery的dom操作 10-27 1课程回顾 10-27 2 jquery的dom操作 内部插入 外部插入 10-27 3 jquery节点操作 10-27 4 练习题讲解 10-27 5 jquery属性操作 获取子元素和...

    jquery1.11.0手册

    jQuery 1.11.0 速查表 核心 jQuery 核心函数 jQuery([sel,[context]]) jQuery(html,[ownerDoc])1.8* ... 数组和对象操作 $.each(object,[callback]) $.extend([d],tgt,obj1,[objN]) $.grep(array,fn,[invert]) ...

    ember-jquery-autocomplete:Ember Bridge的Ember组件jQuery-自动完成

    灰烬jQuery自动完成...autocomplete vocabulary=content value=content.selectedColor auto-focus=true}}特性vocabulary用于查找的余烬对象数组。笔记绑定到组件值的变量应在应用程序中初始化(例如,使用空字符串)

    Jquery 1.3 简体中文手册

    数组和对象操作 $.each(object, [callback]) $.extend([d],tgt,obj1,[objN]) $.grep(array, fn, [invert]) $.makeArray(obj) $.map(array, callback) $.inArray(value, array) $.merge(first, second) $....

    JavaScript权威指南(第六版) 清晰-完整

    4.2 对象和数组的初始化表达式 4.3 函数定义表达式 4.4 属性访问表达式 4.5 调用表达式 4.6 对象创建表达式 4.7 运算符概述 4.8 算术表达式 4.9 关系表达式 4.10 逻辑表达式 4.11 赋值表达式 4.12 表达式计算 4.13 ...

    JQuery 1.3 中文参考手册

    数组和对象操作 $.each(object, [callback]) $.extend([d],tgt,obj1,[objN]) $.grep(array, fn, [invert]) $.makeArray(obj) $.map(array, callback) $.inArray(value, array) $.merge(first, second) $....

    JavaScript权威指南(第6版)(中文版)

    4.2 对象和数组的初始化表达式 4.3 函数定义表达式 4.4 属性访问表达式 4.5 调用表达式 4.6 对象创建表达式 4.7 运算符概述 4.8 算术表达式 4.9 关系表达式 4.10 逻辑表达式 4.11 赋值表达式 4.12 表达式计算 4.13 ...

    JavaScript权威指南(第6版)

    4.2 对象和数组的初始化表达式 4.3 函数定义表达式 4.4 属性访问表达式 4.5 调用表达式 4.6 对象创建表达式 4.7 运算符概述 4.8 算术表达式 4.9 关系表达式 4.10 逻辑表达式 4.11 赋值表达式 4.12 表达式计算 4.13 ...

    JavaScript权威指南(第6版) 中文版

    4.2 对象和数组的初始化表达式 61 4.3 函数定义表达式 62 4.4 属性访问表达式 63 4.5 调用表达式 64 4.6 对象创建表达式 64 4.7 运算符概述 65 4.8 算术表达式 69 4.9 关系表达式 74 4.10 逻辑表达式 79 4.11 赋值...

Global site tag (gtag.js) - Google Analytics