zoukankan      html  css  js  c++  java
  • jquery对象的数组特性

    1. 2.3、jquery对象的数组特性   
    2. 从上面一小节可以看出jquery构建函数完成了查找或转换或其它的功能,其结果就是找到元素,查找,转找不过是方式而已。找到元素就得找个地方去存储起来。这个地方是就是这一节要分析的。   
    3. 存储有序数据的地方(集合)在JS中最好的当然是数组。那么又如何在jQuery内面实现数组呢?可以采用如下的方式:   
    4. jQuery.fn.prototype=new Array();   
    5. 在上一节中的this.setArray(arr)函数中加上   
    6.   Array.apply(this,arr);   
    7. 如果还要完美一点,就加上:   
    8. jQuery.fn.prototype.constructor=jQuery。   
    9. 这样我们继承了数组的所有特性,又可以在Jquery对象进行数组的功能扩展。但是jQuery并没有这样采用继承Array而实现这个内部的集合。它采用了Array-Like的对象的实现(见JavaScript: The Definitive Guide, 5th Edition7.8节)。   
    10. 类数组的对象还是对象,只不过像数组。数组与对象其实是没有什么好大的区别的,有序和无序的集合是它们区别。这个区别反应在数组有的length属性。当添加元素它会自动加上相对的个数,当删除元素,它会自动减去相对的个数。   
    11. 看一下jQuery是怎么实现的:   
    12. // 第一种情况 Handle $(DOMElement)单个Dom 元素,忽略上下文   
    13.         if (selector.nodeType) {                                            ②   
    14.             this[0] = selector;   
    15.             this.length = 1;   
    16.             return this;   
    17.         }          
    18. 这是它的第一种实现方法,通过this[0]来直接设定第一个位置的Dom元素,同时设定length=1。这里我们可以看出对象与数组一样都是采用key/Value对的形式存在对象中。上面的Json形式为{0:aDom,length=1}。这里细细分析一下数组,数组是继承于对象。其[]的解释分析最终结果可以看作{}构的对象,对[]或数组的构建时会进行把index(如0.1,….)做为对象属性的key。把数组中的值做为其对应的value。同时改变length的值。这也就是说为什么本质上对象与数组没有多大的区别。在很多的源码中,如YUI中都采用对象的形式来构建多维数组。   
    19. this.setArray(jQuery.makeArray(selector));   
    20. 是其第二种实现的方法,上面实现是单个的元素,这个实现的多个元素的集合。它首先调用了jQuery.makeArray(selector)这个静态方法把集合(类数组)转换成数组。   
    21. 上面已经分析了数组和对象都可以采用obj.[attr]的形式来取得其key对应的value。对于集合或类数组,必须要求其实现length属性,有了length的长度,那么就从0~length-1的key属性中取得对应的value就可以了:   
    22. //把类数组的集合转换成数组,如果是单个元素就生成单个元素的数组。   
    23. makeArray: function( array ) {   
    24.     var ret = [];   
    25.     if( array != null ){    var i = array.length;   
    26.     //单个元素,但window, string、 function有 'length'的属性,加其它的判断   
    27.       if( i == null || array.split || array.setInterval || array.call )   
    28.           ret[0] = array;   
    29.       else//类数组的集合   
    30.           while( i )    ret[--i] = array[i];//Clone数组   
    31.      }   
    32. return ret;   
    33.     },   
    34. 生成了一个标准的数组,那么接下来setArray来干什么呢?   
    35. // 把array-like对象的元素全部push当前jquery对象。   
    36.     setArray : function(elems) {   
    37.         this.length = 0;//初始化长度,因为push会在原始的length++   
    38.         Array.prototype.push.apply(this, elems);   
    39.         return this;   
    40.     },   
    41. 这个调用了Array.prototype.push来自动修改length的属性值(当然是加入了元素)。由此可以推想到Array中众多的方法(如shift)都可以看作改变length的值在对象的key/value对中完成无序到有序或重新排序的工作。实际上Array等是采用C或C++来实现的。但是它构出的JS特性让我们可以这样去思考采用JavaScript的实现方式。   
    42. 上面的setArray(elems)函数只是会改变当前jQuery对象的集合,它会清除这个对象集合中以前的元素。但是有的时候我们想保存原来的集合中元素,同时也能就新传入的元素进行jquery对象的操作。它提供了pushStack函数来新建一个jQuery对象同时保存原来对象的引用。这样就可能在需要时用到自己所要的对象:   
    43.     pushStack : function(elems) {// 采用jQuery构建新对象,同时引用老对象。   
    44.         var ret = jQuery(elems);// 构建新的jquery对象   
    45.         ret.prevObject = this;// 保存老的对象的引用   
    46.         return ret;   
    47.     },   
    48. 返回的是新构建成的对象,有着jQuery对象的全部功能,同时还可以通过prevObject来访问原来的老对象。   
    49.   
    50. 构建了类数组,那么还得提供一些方法来操作这个集合,对于集合的操作无非就是定位元素,查找元素,复制(slice)和删除的操作(splice)等。jQuery还提供each,map的扩展。   
    51. 这些方法只和集合相关,与集合的元素的无关。jQuery提供了众多的和其中元素(DOM元素)相关的方法。   
    52.   
    53. 它提供了两个get元素的方法,get(index)和eq(index),不同是get取得是集合中的元素,而eq则是返回该元素的Clone。不会修改数组。其实可以直接通过[i]来代替get(i)。如果get没有参数则是获得全部元素。   
    54. // 取到本jquery对象的第几个Dom元素,无参数,代表全部的Dom元素   
    55.     get : function(num) {   
    56.         return num == undefined ? jQuery.makeArray(this) : this[num];   
    57.     },   
    58. // 获取第N个元素 。这个元素的位置是从0算起。   
    59.     eq : function(i) {   
    60.         return this.slice(i, +i + 1);   
    61.     },   
    62. 这两个函数就不用分析了。接下来看看如何实现在集合中定位元素:   
    63. / 找到elem在本jquery对象的位置(index)   
    64.     index : function(elem) {   
    65.         var ret = -1;   
    66.         return jQuery.inArray( // 如是jQuery对象就取第一个元素   
    67.                 elem && elem.jquery ? elem[0] : elem, this);   
    68.     },   
    69.   
    70. // 判断elem元素在array中的位置(index) 静态方法   
    71.     inArray : function(elem, array) {   
    72.             for (var i = 0, length = array.length;i < length; i++)   
    73.                 // Use === because on IE, window == document   
    74.                 if (array[i] === elem)   
    75.                     return i;   
    76.             return -1;   
    77.         },   
    78. inArray是jQuery的静态方法,而index是通过调用inArray来实现其定位的功能。Index的函数支持的参数可以是jQuery对象或Dom元素,而inArray则是实用方法,支持任何的元素。   
    79.   
    80. Jquery提供了如数组中slice复制的功能的方法,还提供类似concat的静态方法merge。Slice是通过Array中slice来实现的:   
    81.   / 代理数组的slice,同样的操作。   
    82.     slice : function() {   
    83.         return this.pushStack(Array.prototype.slice.apply(this, arguments));   
    84.     },   
    85. 它返回生成新的jQuery对象。这个对象的集合就是要复制后的集合。对于merge,它是静态方法,实现把第二个元素追加到第一个参数的数组中。   
    86. // 把second 元素追加到first的数组中。   
    87.         merge : function(first, second) {   
    88.      // We have to loop this way because IE & Opera overwrite the length   
    89.      // expando of getElementsByTagName   
    90.         var i = 0, elem, pos = first.length;   
    91.         // Also, we need to make sure that the correct elements are being   
    92.         // returned (IE returns comment nodes in a '*' query)   
    93.             if (jQuery.browser.msie) {   
    94.                 while (elem = second[i++])   
    95.                     if (elem.nodeType != 8)   
    96.                         first[pos++] = elem;   
    97.   
    98.             } else  
    99.                 while (elem = second[i++])   
    100.                     first[pos++] = elem;   
    101.   
    102.             return first;   
    103.         },   
    104. Jquery的each是对集合中每个元素都执行回调函数。   
    105.     // 当前jquery对象中每个元素都执行callback(index,elem)函数   
    106.     each : function(callback, args) {// 返回this   
    107.     // 其调用了jQuery的静态方法。prototype中的mothodize是解决这类问题的好方法   
    108.         return jQuery.each(this, callback, args);   
    109.     },     
    110. 它通过调用jQuery.each这个静态方法来完成功能的:   
    111. // 对object中的每个对象都执行callback函数进行处理。args仅仅内部用   
    112.      each : function(object, callback, args) {   
    113.             var name, i = 0, length = object.length;   
    114.             // 和else的处理差不多,args的传参代替object的属性值   
    115.             if (args) {   
    116.                 if (length == undefined) {   
    117.                     for (name in object)   
    118.                         if (callback.apply(object[name], args) === false)   
    119.                             break;   
    120.                 } else  
    121.                     for (;i < length;)   
    122.                         if (callback.apply(object[i++], args) === false)   
    123.                             break;   
    124.             } else {   
    125.                // 不是array-like的object,对每个属性进行callback函数的调用   
    126.     if (length == undefined) {   
    127.                 for (name in object)   
    128. if (callback.call(object[name], name, object[name]) === false)   
    129.                         break;   
    130.                    } else  
    131.                     // array-like object,采用数组的形式来处理   
    132.      for (var value = object[0];i < length   && callback.call(value, i, value) !== false; value = object[++i]) {}   
    133.             }   
    134.             return object;   
    135.         },   
    136. 该静态方法支持第一个参数的类数组(数组)或对象。是数组就对每个元素进行callback的操作。如果是对象,就是对每个属性值进行callback的操作。这个callback回调函数的格式如下:callback:function(index,value)。Index是索引号,value是数组的index对应的元素或对象的第index个处理的属性。如果使用args参数,那callback回调函数的格式如下:callback:function(args)。Args是给回调函数设定参数。再看一下jQuery对象的each。它的第二个参数args就是采用传入的args直接进行给callback设定参数,而不是默认提集合中index和对应的元素,但执行的次数还是集合的length次。   
    137.   
    138. Jquery的map是将一组元素转换成其他数组(通过回调函数返回值组成的)   // 将一组元素转换成其他数组 然后根据这个数组构建新的jquery对象。。   
    139.     map : function(callback) {   
    140.         return this.pushStack(jQuery.map(this, function(elem, i) {   
    141.             return callback.call(elem, i, elem);   
    142.         }));   
    143.     },   
    144. 这个函数首先通过jQuery.map(this, function(elem, i){}来把this的jQuery对象集合的每个元素当作回调函数的elem的参数传到回调函数中。而这个回调函数又执行实例方法的map : function(callback)中callback函数,也就是jQuery.map中的回调仅仅是传参代理的功能。jQuery.map通过代理的回调来取得转换而成的元素集合。   
    145. 接下来就是采用pushStack把这集合的元素构建成新的jQuery对象并返回,同时保存原jQuery对象的引用。   
    146. 看下Map的静态方法:   
    147.     // 返回对elems每个元素都进行操作的callback函数的返回值的集合。   
    148.         map : function(elems, callback) {   
    149.             var ret = [];              
    150.             for (var i = 0, length = elems.length;i < length; i++) {   
    151.                 var value = callback(elems[i], i);   
    152.                 if (value != null)//说明转换的集合的个数可能少于原来的集合   
    153.                     ret[ret.length] = value;   
    154.             }   
    155.             return ret.concat.apply([], ret);//采用array的concat实现   
    156.         }   
    157. Map的静态方法返回每个callback返回的元素组成的数组。  
  • 相关阅读:
    hdu 5517 Triple(二维树状数组)
    bzoj 3998: [TJOI2015]弦论(后缀自动机)
    hdu 5008 Boring String Problem(后缀数组+rmq)
    hdu 4622 Reincarnation(后缀自动机)
    hdu 6025 card card card(双指针)
    寒武纪camp Day3
    寒武纪camp Day2
    寒武纪camp Day1
    Codeforces 920G(二分+容斥)
    Codeforces 920E(补图BFS)
  • 原文地址:https://www.cnblogs.com/rooney/p/1346133.html
Copyright © 2011-2022 走看看