Javascript中Array.prototype.map()详解


Posted in Javascript onOctober 22, 2014

在我们日常开发中,操作和转换数组是一件很常见的操作,下面我们来看一个实例:

var desColors = [],

    srcColors = [

        {r: 255, g: 255, b: 255 }, // White

        {r: 128, g: 128, b: 128 }, // Gray

        {r: 0,   g: 0,   b: 0   }  // Black

    ];
for (var i = 0, ilen = srcColors.length; i < ilen; i++) {

    var color = srcColors[i],

        format = function(color) {

            return Math.round(color / 2);

        };
    desColors.push( {

        r: format(color.r),

        g: format(color.g),

        b: format(color.b)

    });

}
// Outputs:

// [

//    {r: 128, g: 128, b: 128 },

//    {r: 64,  g: 64,  b: 64  },

//    {r: 0,   g: 0,   b: 0   }

// ];

console.log(desColors);

从上例可以看出,所有的操作重复率都比较高,如何来优化呢,幸运的是Ecmascript 5给我们提供了一个map方法,我们可以利用它来优化上例:

var srcColors = [

        {r: 255, g: 255, b: 255 }, // White

        {r: 128, g: 128, b: 128 }, // Gray

        {r: 0,   g: 0,   b: 0   }  // Black

    ],

    desColors = srcColors.map(function(val) {

        var format = function(color) {

            return Math.round(color/2);

        };

        return {

            r: format(val.r),

            g: format(val.g),

            b: format(val.b)

        }

    });

// Outputs:

// [

//    {r: 128, g: 128, b: 128 },

//    {r: 64,  g: 64,  b: 64  },

//    {r: 0,   g: 0,   b: 0   }

// ];

console.log(desColors);

从上例看以看出,我们使用map替换掉了for循环部分,从而只需要关心每个元素自身的实现逻辑。关于map方法详情请戳这里。

1.map基本定义:
array.map(callback[, thisArg]);

map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数。callback 每次执行后的返回值组合起来形成一个新数组。 callback 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 delete 删除的索引则不会被调用。

callback 函数会被自动传入三个参数:数组元素,元素索引,原数组本身。

如果 thisArg 参数有值,则每次 callback 函数被调用的时候,this 都会指向 thisArg 参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 null 或 undefined,则 this 指向全局对象 。

map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。

当一个数组运行 map 方法时,数组的长度在调用第一次 callback 方法之前就已经确定。在 map 方法整个运行过程中,不管 callback 函数中的操作给原数组是添加还是删除了元素。map 方法都不会知道,如果数组元素增加,则新增加的元素不会被 map 遍历到,如果数组元素减少,则 map 方法还会认为原数组的长度没变,从而导致数组访问越界。如果数组中的元素被改变或删除,则他们被传入 callback 的值是 map 方法遍历到他们那一刻时的值。

2.map实例:

//实例一:字符串上调用map方法

var result = Array.prototype.map.call("Hello world", function(x, index, arr) {

    //String {0: "H", 1: "e", 2: "l", 3: "l", 4: "o", 5: " ", 6: "w", 7: "o", 8: "r", 9: "l", 10: "d", length: 11}

    console.log(arr);

    return x.charCodeAt(0);

});

//Outputs: [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100] 

console.log(result);

上例演示了在一个String上使用map方法获取字符串中每个字符所对应的 ASCII 码组成的数组。请注意看打印的console.log(arr)打印的结果。

//实例二:下面的操作结果是什么?

var result = ["1", "2", "3"].map(parseInt);

//Outputs: [1, NaN, NaN] 

console.log(result);

也许你会有疑问,为什么不是[1,2,3]呢?我们知道parseInt方法可接收两个参数,第一个参数为需要转换的值,第二个参数为进制数,不了解的可以戳这里。当我们使用map方法的时候,callback函数接收三个参数,而parseInt最多只能接收两个参数,以至于第三个参数被直接舍弃,与此同时,parseInt把传过来的索引值当成进制数来使用.从而返回了NaN。看下面的输出结果:

//Ouputs: 1

console.log(parseInt("1", 0));

//Ouputs: 1

console.log(parseInt("1", undefined));

//Ouputs: NaN

console.log(parseInt("2", 1));

//Ouputs: NaN

console.log(parseInt("3", 2));

后面两个很容易理解,但是前两个为什么返回1呢?为了解释这个问题,我们看看官方的描述:
If radix is undefined or 0 (or absent), JavaScript assumes the following:
a) If the input string begins with “0x” or “0X”, radix is 16 (hexadecimal) and the remainder of the string is parsed.
b) If the input string begins with “0″, radix is eight (octal) or 10 (decimal). Exactly which radix is chosen is implementation-dependent. ECMAScript 5 specifies that 10 (decimal) is used, but not all browsers support this yet. For this reason always specify a radix when using parseInt.
c) If the input string begins with any other value, the radix is 10 (decimal).
在第三点中当string为其他值时,进制默认为10。

那么我们如何修改才能使上例正常输出呢?看下例:

var result = ["1", "2", "3"].map(function(val) {

    return parseInt(val, 10);

});

//Outputs: [1, 2, 3] 

console.log(result);

3.map方法的兼容性:
map方法在IE8及以下浏览器不支持,要想兼容老版本的浏览器,可以:

a) Don't use map.b) Use something like es5-shim to make older IE's support map.c) Use the _.map method in Underscore or Lodash for an equivalent utility function.

以上就是对map方法的理解,希望对初学者有所帮助,文中不妥之处,还望斧正!

Javascript 相关文章推荐
JAVASCRIPT实现的WEB页面跳转以及页面间传值方法
May 13 Javascript
ASP.NET MVC中EasyUI的datagrid跨域调用实现代码
Mar 14 Javascript
javascript的tab切换原理与效果实现方法
Jan 10 Javascript
jQuery实现3D文字特效的方法
Mar 10 Javascript
PHP结合jQuery实现的评论顶、踩功能
Jul 22 Javascript
js实现select跳转菜单新窗口效果代码分享(超简单)
Aug 21 Javascript
AngularJS通过$sce输出html的方法
Sep 22 Javascript
webpack配置文件和常用配置项介绍
Apr 28 Javascript
js 将canvas生成图片保存,或直接保存一张图片的实现方法
Jan 02 Javascript
vue 设置proxyTable参数进行代理跨域
Apr 09 Javascript
vue2.0 实现导航守卫(路由守卫)
May 21 Javascript
vue开发chrome插件,实现获取界面数据和保存到数据库功能
Dec 01 Vue.js
javascript数组详解
Oct 22 #Javascript
Javascript 数组排序详解
Oct 22 #Javascript
Javascript中arguments对象详解
Oct 22 #Javascript
Javascript中的默认参数详解
Oct 22 #Javascript
js style动态设置table高度
Oct 21 #Javascript
js读写json文件实例代码
Oct 21 #Javascript
一个JavaScript防止表单重复提交的实例
Oct 21 #Javascript
You might like
Views rows style模板重写代码
2011/05/16 PHP
浅析echo(),print(),print_r(),return之间的区别
2013/11/27 PHP
PHP fastcgi模式上传大文件(大约有300多K)报错
2014/09/28 PHP
javascript游戏开发之《三国志曹操传》零部件开发(五)可移动地图的实现
2013/01/23 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
div拖拽插件——JQ.MoveBox.js(自制JQ插件)
2013/05/17 Javascript
javascript中文本框中输入法切换的问题
2013/12/10 Javascript
流量统计器如何鉴别C#:WebBrowser中伪造referer
2015/01/07 Javascript
基于OL2实现百度地图ABCD marker的效果
2015/10/01 Javascript
js仿支付宝填写支付密码效果实现多方框输入密码
2016/03/09 Javascript
浅析angularJS中的ui-router和ng-grid模块
2016/05/20 Javascript
微信小程序开发之圆形菜单 仿建行圆形菜单实例
2016/12/12 Javascript
开源免费天气预报接口API及全国所有地区代码(国家气象局提供)
2016/12/26 Javascript
vue学习笔记之vue1.0和vue2.0的区别介绍
2017/05/17 Javascript
Angularjs自定义指令Directive详解
2017/05/27 Javascript
json2.js 入门教程之使用方法与实例分析
2017/09/14 Javascript
让bootstrap的carousel支持滑动滚屏的实现代码
2017/11/27 Javascript
JavaScript寄生组合式继承实例详解
2018/01/06 Javascript
centos 上快速搭建ghost博客方法分享
2018/05/23 Javascript
JavaScript中click和onclick本质区别与用法分析
2018/06/07 Javascript
Vue-cli配置打包文件本地使用的教程图解
2018/08/02 Javascript
零基础之Node.js搭建API服务器的详解
2019/03/08 Javascript
vue+elementUI实现图片上传功能
2019/08/20 Javascript
layer实现弹出层自动调节位置
2019/09/05 Javascript
vue实现PC端分辨率适配操作
2020/08/03 Javascript
Vue如何跨组件传递Slot的实现
2020/12/14 Vue.js
Python程序中设置HTTP代理
2016/11/06 Python
Python之自动获取公网IP的实例讲解
2017/10/01 Python
机器学习python实战之决策树
2017/11/01 Python
特征脸(Eigenface)理论基础之PCA主成分分析法
2018/03/13 Python
Python常用库大全及简要说明
2020/01/17 Python
python性能测试工具locust的使用
2020/12/28 Python
HTML5 CSS3打造相册效果附源码下载
2014/06/16 HTML / CSS
运动会广播稿50字
2014/01/26 职场文书
小学语文课《掌声》教学反思
2016/03/03 职场文书
2019个人半年工作总结
2019/06/21 职场文书