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


Posted in Javascript onJuly 09, 2015

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

map: function( callback ) {
    return this.pushStack( jQuery.map(this, function( elem, i ) {
      return callback.call( elem, i, elem );
    }));
  },

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

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

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

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

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

参数
arrayOrObject,callbackArray/Object,FunctionV1.6
arrayOrObject:数组或者对象。

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

函数可返回任何值。

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

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

示例1:

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

示例2:

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

示例3:

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

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

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

例如:

var items = [1,2,3,4]; 
$.each(items, function() { 
alert('this is ' + this); 
}); 
var newItems = $.map(items, function(i) { 
return i + 1; 
}); 
// newItems is [2,3,4,5]
//使用each时,改变的还是原来的items数组,而使用map时,不改变items,只是新建一个新的数组。

var items = [0,1,2,3,4,5,6,7,8,9]; 
var itemsLessThanEqualFive = $.map(items, function(i) { 
// removes all items > 5 
if (i > 5) 
return null; 

return i; 
}); 
// itemsLessThanEqualFive = [0,1,2,3,4,5]

言归正传回到map源码

// arg is for internal usage only
  map: function( elems, callback, arg ) {
    var value, key, ret = [],
      i = 0,
      length = elems.length,
      // jquery objects are treated as arrays
      isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;

    // Go through the array, translating each of the items to their
    if ( isArray ) {
      for ( ; i < length; i++ ) {
        value = callback( elems[ i ], i, arg );

        if ( value != null ) {
          ret[ ret.length ] = value;
        }
      }

    // Go through every key on the object,
    } else {
      for ( key in elems ) {
        value = callback( elems[ key ], key, arg );

        if ( value != null ) {
          ret[ ret.length ] = value;
        }
      }
    }

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

首先还是声明几个变量为接下来的遍历做准备,其中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循环

// Go through the array, translating each of the items to their
    if ( isArray ) {
      for ( ; i < length; i++ ) {
        value = callback( elems[ i ], i, arg );

        if ( value != null ) {
          ret[ ret.length ] = value;
        }
      }

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

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

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

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

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

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

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

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

Javascript 相关文章推荐
node.js开机自启动脚本文件
Dec 24 Javascript
JQuery操作元素的css样式
Mar 09 Javascript
JS时间特效最常用的三款
Aug 19 Javascript
基于javascript制作微信聊天面板
Aug 09 Javascript
阻止表单提交按钮多次提交的完美解决方法
May 16 Javascript
VUEJS实战之修复错误并且美化时间(2)
Jun 13 Javascript
AngularJS基础 ng-hide 指令用法及示例代码
Aug 01 Javascript
jQuery+json实现动态创建复杂表格table的方法
Oct 25 Javascript
使用AngularJS2中的指令实现按钮的切换效果
Mar 27 Javascript
vue2.0 根据状态值进行样式的改变展示方法
Mar 13 Javascript
详解Vite的新体验
Feb 22 Javascript
React-vscode使用jsx语法的问题及解决方法
Jun 21 Javascript
jQuery实现鼠标点击弹出渐变层的方法
Jul 09 #Javascript
javascript+ajax实现产品页面加载信息
Jul 09 #Javascript
浅谈JavaScript中null和undefined
Jul 09 #Javascript
兼容各大浏览器的JavaScript阻止事件冒泡代码
Jul 09 #Javascript
JavaScript包装对象使用详解
Jul 09 #Javascript
jquery实现表单验证并阻止非法提交
Jul 09 #Javascript
jQuery实现tab选项卡效果的方法
Jul 08 #Javascript
You might like
php中使用parse_url()对网址进行解析的实现代码(parse_url详解)
2012/01/03 PHP
PHP在innodb引擎下快速代建全文搜索功能简明教程【基于xunsearch】
2016/10/14 PHP
学习ExtJS(二) Button常用方法
2009/10/07 Javascript
使用Grunt.js管理你项目的应用说明
2013/04/24 Javascript
jQuery弹性滑动导航菜单实现思路及代码
2013/05/02 Javascript
jQuery学习笔记之 Ajax操作篇(一) - 数据加载
2014/06/23 Javascript
Node.js中的事件驱动编程详解
2014/08/16 Javascript
js jquery获取当前元素的兄弟级 上一个 下一个元素
2015/09/01 Javascript
使用EVAL处理jqchart jquery 折线图返回数据无效的解决办法
2015/11/26 Javascript
JavaScript校验Number(4,1)格式的数字实例代码
2017/03/13 Javascript
微信小程序实战之顶部导航栏(选项卡)(1)
2020/06/19 Javascript
angularjs利用directive实现移动端自定义软键盘的示例
2017/09/20 Javascript
vue-cli启动本地服务局域网不能访问的原因分析
2018/01/22 Javascript
vue-baidu-map 进入页面自动定位的解决方案(推荐)
2018/04/28 Javascript
详解webpack引入第三方库的方式以及注意事项
2019/01/15 Javascript
详解Vue webapp项目通过HBulider打包原生APP(vue+webpack+HBulider)
2019/02/02 Javascript
微信小程序左滑删除实现代码实例
2019/09/16 Javascript
[02:36]DOTA2英雄基础教程 斯拉克
2013/11/29 DOTA
pyv8学习python和javascript变量进行交互
2013/12/04 Python
Pycharm编辑器技巧之自动导入模块详解
2017/07/18 Python
windows下python安装pip图文教程
2018/05/25 Python
使用pytorch完成kaggle猫狗图像识别方式
2020/01/10 Python
详解h5页面在不同ios设备上的问题总结
2019/03/01 HTML / CSS
zooplus意大利:在线宠物商店
2019/08/07 全球购物
《望洞庭》教学反思
2014/02/16 职场文书
《赶海》教学反思
2014/04/20 职场文书
优秀的应届生自荐信
2014/05/23 职场文书
本科毕业生自荐信
2014/05/26 职场文书
有限责任公司股东合作协议书
2014/12/02 职场文书
2016情人节宣传语
2015/07/14 职场文书
创业不要错过,这4种餐饮新模式
2019/07/18 职场文书
30岁前绝不能错过的10本书
2019/08/08 职场文书
Python基础知识之变量的详解
2021/04/14 Python
解析laravel使用workerman用户交互、服务器交互
2021/04/28 PHP
Python实现文字pdf转换图片pdf效果
2022/04/03 Python
VUE解决跨域问题Access to XMLHttpRequest at
2022/05/06 Vue.js