jQuery源码阅读(十一)---each、map、grep、merge、makeArray、inArray解读
来源:互联网 发布:算法 英文版 pdf 编辑:程序博客网 时间:2024/05/29 19:32
这两天都在看jQuery源码中的静态方法,上一篇博客介绍了类型检测这一类静态方法,这次主要对后面几个常用的方法进行分析。主要包括:
each: function(){} map: function(){} grep: function()merge: function(){}makeArray: function(){}inArray: function(){}
each、map、grep
each、map、grep这三个函数是比较相似的,所以想放在一起来分析。
首先先要了解三个函数的功能:
var arr = [2,3,5,9];var res = $.each(arr, function(i, item){ console.log(i + ' ' + item);})
var obj = [3,5,7,9,2, 4, 6, 8];res = $.map(obj, function( item, i){ if(item % 2 == 0) { return item; }});
var arr = [4,2,8,6,4,3,0,6];var res = $.grep(arr, function(item, i){ return item > 4; //过滤条件,返回一个数组 });var res1 = $.grep(arr, function(item, i){ return item > 4; //过滤条件,返回一个数组 }, true);
上面是三种方法的功能测试,可以看到,each主要是对数组(对象)中的每个元素进行遍历或者一系列操作;map和grep的话其实都可以认为是过滤函数,按照一定的规则去过滤和映射,不同的是,map可以对 对象来操作,但是grep只能过滤数组。
下来分析一下源码。
each源码:
function( object, callback, args ) { var name, i = 0, length = object.length, //如果是对象,没有length属性 //判断是否为对象或者函数,函数的话有length属性,所以需要另外判断 isObj = length === undefined || jQuery.isFunction( object ); //args是要传入到callback里面的参数,注意这个args需要传数组的形式,因为下面利用的是callback.apply。 if ( args ) { //整体思路是分别对对象和数组(或伪数组)处理; //object为对象时,用for ... in 来遍历 if ( isObj ) { for ( name in object ) { if ( callback.apply( object[ name ], args ) === false ) { break; } } } else { //object为数组(伪数组)时,直接利用for循环。 //对每一个元素分别调callback方法 for ( ; i < length; ) { if ( callback.apply( object[ i++ ], args ) === false ) { break; } } } } else { //无参数情况与上面情况类似,默认的参数为元素索引index和数组元素item if ( isObj ) { for ( name in object ) { if ( callback.call( object[ name ], name, object[ name ] ) === false ) { break; } } } else { for ( ; i < length; ) { if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) { break; } } } } return object;}
grep源码:
function( elems, callback, inv ) { //ret空数组是用来保存过滤元素的,最后作为结果返回 var ret = [], retVal; inv = !!inv; //inv表示是否反转结果;!!inv是用来将inv转换成Boolean类型的。默认不传改参数,就是false for ( var i = 0, length = elems.length; i < length; i++ ) { //对数组中每个元素执行过滤规则(即callback函数),并将返回的结果转换为Boolean值 retVal = !!callback( elems[ i ], i ); //若有返回值,retVal为true; 默认情况下inv为false,这时将当前元素Push进ret数组中,保存起来。 //同理,若inv设为true,表示将未满足过滤规则的元素push进结果数组里。 if ( inv !== retVal ) { ret.push( elems[ i ] ); } } return ret;}
map源码:
function( elems, callback, arg ) { var value, key, ret = [], i = 0, length = elems.length, //判断elems是否为数组(或伪数组) //jQuery对象算是伪数组 isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; // 当elems为数组时,for循环遍历每个元素,并对每个元素执行callback函数,返回结果加到ret数组里 if ( isArray ) { for ( ; i < length; i++ ) { value = callback( elems[ i ], i, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } else { //当elems为对象时,利用for...in 遍历每个元素,并对每个元素调callback函数 for ( key in elems ) { value = callback( elems[ key ], key, arg ); if ( value != null ) { ret[ ret.length ] = value; } } } //最后是对结果的扁平化 return ret.concat.apply( [], ret );}
这里主要对map函数最后 扁平化进行分析。这是为了防止数组嵌套的情况。假设这么一种情况:
var obj = [ [1,2,3], [4,5,6]];res = $.map(obj, function( item, i){ return item; });
可以看到最后得到的结果数组里,中间并没有嵌入数组。这是如何解决的呢?
在jQuery源码中,利用了apply和数组的原生方法concat。
ret.concat.apply( [], ret );
concat作用是将数组进行连接,并返回一个新的数组。利用apply,首先将空数组和ret数组中第一个元素进行连接,返回一个新的数组,然后再将新的数组和ret中第二个元素连接,以此类推。最终得到一个新数组。
makeArray、inArray、merge
这三个方法都相当于是数组(类数组)上的操作。
makeArray:将传入的参数转换成数组inArray: 判断某个元素是否在数组中merge: 将两个数组合并成数组
makeArray源码:
function( array, results ) { var ret = results || []; if ( array != null ) { var type = jQuery.type( array ); //array为对象,字符串,函数,正则,Window对象,都认为是一个整体,直接将其加入到ret数组中 if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) { push.call( ret, array ); } else { //array为数组或伪数组,调用jQuery.merge方法,这在[之前的博客中](http://blog.csdn.net/u010046318/article/details/74223908)已讲过 jQuery.merge( ret, array ); } } return ret;}
inArray源码:
function( elem, array, i ) { var len; //不对对象和字符串起作用 if ( array ) { //调原生的Array.prototype.indexOf方法 if ( indexOf ) { return indexOf.call( array, elem, i ); } //若浏览器不支持上面方法,下面手动实现,遍历一遍,找到数组中元素与elem相等的元素,并返回index。没找到,就返回-1. len = array.length; i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; for ( ; i < len; i++ ) { if ( i in array && array[ i ] === elem ) { return i; } } } return -1;}
到这里,jQuery静态方法基本上已经整理完了,其他的几个方法不是很常用的,所以大致过了一遍。下来的部分应该就是jQuery各个模块的实现了,比如回调对象,延迟对象,队列,异步队列,Sizzle等等,这些底层的一些东西也用到了上面提到的静态方法。所以后面看的过程中,一方面学习新的思想和技巧,另一方面回顾之前总结的方法。
阅读全文
0 0
- jQuery源码阅读(十一)---each、map、grep、merge、makeArray、inArray解读
- jQuery数组处理完全详解($.each,$.grep,$.map,$.merge,$.inArray,$.unique,$.makeArray)
- jQuery数组($.each,$.grep,$.map,$.merge,$.inArray,$.unique,$.makeArray)处理函数详解
- jQuery数组($.each,$.grep,$.map,$.merge,$.inArray,$.unique,$.makeArray)处理函数详解
- jQuery数组($.each,$.grep,$.map,$.merge,$.inArray,$.unique,$.makeArray)处理函数详解
- Query数组($.each,$.grep,$.map,$.merge,$.inArray,$.unique,$.makeArray)处理函数详解
- jquery工具:$.each,grep,map, inArray,merge,unique,uniqueSort,contains,type.....
- jquery源码--isArraylike merge makeArray
- $.grep ,$.map,jquery筛选数组之grep、each、inArray、map的用法及遍历json对象
- jquery源码阅读jQuery.inArray()
- jquery筛选数组之grep、each、inArray、map的用法及遍历json对象
- jquery筛选数组之grep、each、inArray、map的用法及遍历json对象
- jquery筛选数组之grep、each、inArray、map的用法及遍历json对象
- jquery筛选数组之grep、each、inArray、map的用法及遍历json对象 [转]
- jquery筛选数组之grep、each、inArray、map的用法及遍历json对象
- jquery筛选数组之grep、each、inArray、map的用法及遍历json对象
- jquery筛选数组之grep、each、inArray、map的用法及遍历json对象
- $.grep(),$.map(),$.inArray()
- Kafka入门介绍(一)
- Systemd 入门教程:命令篇
- Linux中link,unlink,close,fclose详解
- [LeetCode]493. Reverse Pairs 深入浅出算法讲解和代码示例
- ListIterator等的使用。
- jQuery源码阅读(十一)---each、map、grep、merge、makeArray、inArray解读
- 阿里云上配置hostname使用内网ip,不能使用外网ip
- POJ1426 Find The Multiple
- 强制类型转换
- js-apply()
- php运行原理
- 针对thinkphp中"no input file specified"的解决方法
- RabbitMQ第三篇:采用不同的交换机规则
- eclipse中安装mybatis generator插件自动生成dao、xml、pojo