首页 > 语言 > JavaScript > 正文

jquery.map()方法的使用详解

2024-05-06 16:23:00
字体:
来源:转载
供稿:网友

本文给大家详细介绍了jQuery中的原型方法map的使用指南和源码分析,十分的不错,对于大家学习jQuery非常有帮助,这里推荐给大家。

原型方法map跟each类似调用的是同名静态方法,只不过返回来的数据必须经过另一个原型方法pushStack方法处理之后才返回,源码如下:

 

 
  1. map: function( callback ) { 
  2. return this.pushStack( jQuery.map(thisfunction( elem, i ) { 
  3. return callback.call( elem, i, elem ); 
  4. })); 
  5. }, 

本文主要就是分析静态map方法至于pushStack在下一篇随笔里面分析;

首先了解下map的使用(手册内容)

$.map将一个数组中的元素转换到另一个数组中。

作为参数的转换函数会为每个数组元素调用,而且会给这个转换函数传递一个表示被转换的元素作为参数。

转换函数可以返回转换后的值、null(删除数组中的项目)或一个包含值的数组,并扩展至原始数组中。

参数

arrayOrObject,callbackArray/Object,FunctionV1.6

arrayOrObject:数组或者对象。

为每个数组元素调用,而且会给这个转换函数传递一个表示被转换的元素作为参数。

函数可返回任何值。

另外,此函数可设置为一个字符串,当设置为字符串时,将视为“lambda-form”(缩写形式?),其中 a 代表数组元素。

如“a * a”代表“function(a){ return a * a; }”。

示例1:

 

 
  1. //将原数组中每个元素加 4 转换为一个新数组。 
  2. //jQuery 代码: 
  3. $.map( [0,1,2], function(n){ 
  4. return n + 4; 
  5. }); 
  6. //结果: 
  7. [4, 5, 6] 

示例2:

 

 
  1. //原数组中大于 0 的元素加 1 ,否则删除。 
  2. //jQuery 代码: 
  3. $.map( [0,1,2], function(n){ 
  4. return n > 0 ? n + 1 : null
  5. }); 
  6. //结果: 
  7. [2, 3] 

示例3:

 

 
  1. //原数组中每个元素扩展为一个包含其本身和其值加 1 的数组,并转换为一个新数组 
  2. //jQuery 代码: 
  3. $.map( [0,1,2], function(n){ 
  4. return [ n, n + 1 ]; 
  5. }); 
  6. //结果: 
  7. [0, 1, 1, 2, 2, 3] 

可以看出map方法跟each方法类似通过循环每个对象或者数组的“项”执行回调函数来实现对数组或者对象的操作,但是这两个方法也有很多不同点

比如each()返回的是原来的数组,并不会新创建一个数组,而map则会创建新的数组,;each遍历是this指向当前数组或对象值,map则指向window,因为在源码中并不像each那样使用对象冒充;

例如:

 

 
  1. var items = [1,2,3,4];  
  2. $.each(items, function() {  
  3. alert('this is ' + this);  
  4. });  
  5. var newItems = $.map(items, function(i) {  
  6. return i + 1;  
  7. });  
  8. // newItems is [2,3,4,5] 
  9. //使用each时,改变的还是原来的items数组,而使用map时,不改变items,只是新建一个新的数组。 
  10.  
  11. var items = [0,1,2,3,4,5,6,7,8,9];  
  12. var itemsLessThanEqualFive = $.map(items, function(i) {  
  13. // removes all items > 5  
  14. if (i > 5)  
  15.   return null;  
  16.   return i;  
  17. });  
  18. // itemsLessThanEqualFive = [0,1,2,3,4,5] 

言归正传回到map源码

 

 
  1. // arg is for internal usage only 
  2. map: function( elems, callback, arg ) { 
  3. var value, key, ret = [], 
  4. i = 0, 
  5. length = elems.length, 
  6. // jquery objects are treated as arrays 
  7. isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; 
  8.  
  9. // Go through the array, translating each of the items to their 
  10. if ( isArray ) { 
  11. for ( ; i < length; i++ ) { 
  12. value = callback( elems[ i ], i, arg ); 
  13.  
  14. if ( value != null ) { 
  15. ret[ ret.length ] = value; 
  16.  
  17. // Go through every key on the object, 
  18. else { 
  19. for ( key in elems ) { 
  20. value = callback( elems[ key ], key, arg ); 
  21.  
  22. if ( value != null ) { 
  23. ret[ ret.length ] = value; 
  24.  
  25. // Flatten any nested arrays 
  26. return ret.concat.apply( [], ret ); 
  27. }, 

首先还是声明几个变量为接下来的遍历做准备,其中jsArray变量用来简单区分对象和数组,这个布尔复合表达式比较长不过只要记住js运算符的有优先顺序就不难理解了,首先括号优先执行然后就是逻辑与》逻辑或》全等》赋值,然后就可以分析啦

首先圆括号里先计算然后结果加上 length !== undefined 、 typeof length === "number这两个必要条件最后的结果再跟elems instanceof jQuery进行逻辑或的运算,简单的说就是isArray为真的情况有:

1、elems instanceof jQuery 为true 换言之就是jquery对象

2、length !== undefined && typeof length === "number" 和 length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems )这三个至少成立一个

可以拆分为3个小情况

length是存在并且是数字而且待遍历的数组或者类数组等length属性大于0 length-1存在 这样就保证了是能遍历的,比如对于jquery对象 domList对象等

length是存在并且是数字而且length属性等于0 如果是0也没关系就是不会遍历

length是存在并且是数字而且待遍历对象是纯数组

满足这些条件之后开始根据isArray的结果分开遍历,对于“数组”采用for循环,对于对象采用for...in循环

 

 
  1. // Go through the array, translating each of the items to their 
  2. if ( isArray ) { 
  3. for ( ; i < length; i++ ) { 
  4. value = callback( elems[ i ], i, arg ); 
  5.  
  6. if ( value != null ) { 
  7. ret[ ret.length ] = value; 

是数组或者类数组的时候直接把循环的每一项的值和指针以及arg参数传入回调函数中执行,arg参数是此方法内部使用的参数,跟each以及一些其他jquery方法很相似,只要在执行回调函数时不返回null就把执行返回的结果添加到新数组中,对象操作亦是如此直接略过

 

 
  1. // Flatten any nested arrays 
  2. return ret.concat.apply( [], ret ); 

最后将结果集扁平化,为什么有这一步呢?因为map是可以扩展数组的在前面第3个示例就是如此:

 

 
  1. $.map( [0,1,2], function(n){ 
  2. return [ n, n + 1 ]; 
  3. }); 

如果是这样使用的话得到的新数组是一个二维数组,所以必须降维

ret.concat.apply( [], ret )等价于[].concat.apply([],ret)关键作用的是apply,因为apply的第二个参数把ret的数组分成多个参数传入给concat把二维数组转化为一维数组这个用法还是值得收藏的的

map方法简单分析完毕,能力有限错误之处望多多指正。

以上所述就是本文的全部内容了,希望大家能够喜欢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

图片精选