原型方法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 onlymap: function( elems, callback, arg ) {var value, key, ret = [],i = 0,length = elems.length,// jquery objects are treated as arraysisArray = 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 theirif ( 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 arraysreturn 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 theirif ( 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 arraysreturn 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方法简单分析完毕,能力有限错误之处望多多指正。

转载于:https://www.cnblogs.com/yy-hh/p/4630968.html

jquery原型方法map的使用和源码分析相关推荐

  1. 深入理解GO语言:map结构原理和源码分析

    Map结构是go语言项目经常使用的数据结构,map使用简单对于数据量不大的场合使用非常合适.Map结构是如何实现的?我们先从测试程序入手,我们希望分析map的创建.插入.查询.删除等流程,因此我们的测 ...

  2. java.lang.ThreadLocal实现原理和源码分析

    java.lang.ThreadLocal实现原理和源码分析 1.ThreadLocal的原理:为每一个线程维护变量的副本.某个线程修改的只是自己的副本. 2.ThreadLocal是如何做到把变量变 ...

  3. Nacos高级特性Raft算法以及原理和源码分析

    Nacos高级特性Raft算法以及原理和源码分析 对比springcloud-config配置中心 springcloud-config工作原理 Nacos的工作原理图 springcloud-con ...

  4. JAVA-LocalDateTime时间格式化,转换时间戳和源码分析

    JAVA-LocalDateTime时间格式化,转换时间戳和源码分析 LocalDateTime LocalDateTime作为java8新加的时间类型,也是后面开发中常用的时间类型.因为没用过之前的 ...

  5. 1、Guava-连接器Joiner使用和源码分析

    Guava-连接器Joiner使用和源码分析 1.Guava-连接器Joiner使用和源码分析 1.1 使用版本 1.2 代码示例 1.2.1 基本使用 1.2.2 集合中Null导致空指针异常 1. ...

  6. Google Mock(Gmock)简单使用和源码分析——源码分析

    源码分析 通过<Google Mock(Gmock)简单使用和源码分析--简单使用>中的例子,我们发现被mock的相关方法在mock类中已经被重新实现了,否则它们也不会按照我们的期待的行为 ...

  7. 【原创】【专栏】《Linux设备驱动程序》--- LDD3源码目录结构和源码分析经典链接

    http://blog.csdn.net/geng823/article/details/37567557 [原创][专栏]<Linux设备驱动程序>--- LDD3源码目录结构和源码分析 ...

  8. java校验框架源码解析_Spring Boot原理剖析和源码分析

    Spring Boot原理剖析和源码分析 依赖管理 问题一:为什么导入dependency时不需要指定版本? spring-boot-starter-parent依赖 org.springframew ...

  9. SRS流媒体服务器——Forward集群搭建和源码分析

    SRS流媒体服务器--Forward集群搭建和源码分析 目录 Forward集群原理 RTMP流转发(Forward)部署实例 Forward集群源码分析 1. Forward集群原理 Forward ...

最新文章

  1. linux内核第一个函数,通过内核源码看函数调用之前世今生 - 极光 - CSDN博客
  2. F5 bigip.conf配置问题
  3. SVN工具的使用 和在Eclipse中安装GPD插件:(多步审批流,因此选择使用工作流(JBPM)来实现)...
  4. myeclipse部署项目后,debug模式启动,总是弹出Class.class文件
  5. php -- 检查是否存在
  6. Linux之bash脚本编程---选择执行
  7. OpenJudge/Poj 1226 Substrings
  8. CSS3动画 - 地球 - 指南针旋转
  9. 全排列---STL方法与递归方法
  10. 【Hadoop Summit Tokyo 2016】中型组织的数据基础设施架构:收集、存储和分析的技巧...
  11. LeetCode 36. Valid Sudoku
  12. 嵌入式系统开发之中断控制的实现
  13. Prototype使用$R()函数
  14. CSDN中Markdown格式(编辑器)语法及其使用
  15. 黑色炫酷网址安全跳转GO跳转PHP源码
  16. iOS根据ts文件路径封装成m3u8文件及m3u8播放
  17. python二级考试大纲小学生_Python语言二级考试大纲
  18. ADM pro破解百度云限速 ADM pro设置方法 ES文件管理器
  19. OpenJ_Bailian - 3164 奇偶排序
  20. (亚马逊澳大利亚)手机充电器 AS/NZS 4417.1 安全标准检测 电池产品UL2054

热门文章

  1. 腾讯无人车开进硅谷!建团队、招人才,国内放出商务岗位
  2. GPU、TPU买起来,新政策让1亿研发费用可多减税375万元
  3. 全球最大地标识别数据集问世:包含200万张图片和3万处地标
  4. 中科视拓获千万pre-A轮融资,想做的不仅仅是人脸识别
  5. 0610PHP基础:运算符、字符串处理函数、解析符号、数组
  6. 教你动手做一个 iOS 越狱 app
  7. rac one node在线relocation
  8. UNIX/Linux系统取证之信息采集案例
  9. Objective-c 中 nil, Nil, NULL和NSNull的区别
  10. 每天学一点flash(76)百度MP3音乐APi接口使用