深入理解 Array.prototype.map()

map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

语法

let new_array = arr.map(function callback(currentValue, index, array) {
// Return element for new_array
}[, thisArg])

参数

  • callback 生成新数组元素的函数,使用三个参数:

    • currentValue 数组中正在处理的当前元素。
    • index 数组中正在处理的当前元素的索引。
    • array map 方法被调用的数组。
  • thisArg 可选的。执行 callback 函数时 使用的this 值。

实际应用

使用指定的方法对数组做批处理

原理

var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
console.log(numbers) // [1, 4, 9]
console.log(roots) // [1, 2, 3]

封装

var numbers = [1, 4, 9];
const arrBat = (arr, func) => arr.map(func)
var roots = arrBat(numbers, Math.sqrt)
console.log(numbers) // [1, 4, 9]
console.log(roots) // [1, 2, 3]

只需要传入对应的处理方法,即可对数组所有元素做批处理。

当然也可对此方法进行二次封装:

var numbers = [1, 4, 9];

const arrBat = (arr, func) => arr.map(func)
const arrToSqrt = (arr) => arrBat(arr, Math.sqrt) // 开平方根
const arrToSquare = (arr) => arrBat(arr, e => Math.pow(e, 2)) // 平方
const arrToRound = (arr) => arrBat(arr, Math.round) // 四舍五入
const arrToCeil = (arr) => arrBat(arr, Math.ceil) // 求上整
const arrToFloor = (arr) => arrBat(arr, Math.floor) // 求下整
const arrToDouble = (arr) => arrBat(arr, e => 2 * e) // 求倍数 arrToSquare(numbers) // [1, 16, 81]
arrToSqrt(numbers) // [1, 2, 3]

多参数函数批量转化的误区

先看下面一个方法:

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

第一反应,这里应该返回的是 [1, 2, 3],然而,实际上返回的却是 [1, NaN, NaN]

这是为什么呢?

事实上,parseInt 接收两个参数,第一个是原始值,第二个是进制值,通常我们使用 parseInt('5') 类似的操作,实际上是默认第二参数为 10,。但注意,在 map 回调函数中,有三个参数,第一个是遍历出来的每一个元素,第二参数为遍历出的元素的下标,第三参数为调用者本身。这里, parseInt 接到了 map 的前两个参数,也就是元素和下标,第三参数被忽略,parseInt 把传过来的索引值当成进制数来使用,从而返回了NaN。

正确的做法是:

const arrToInt = str => Array.prototype.map.call(str, e => parseInt(e, 10))
arrToInt("57832") // [5, 7, 8, 3, 2]
arrToInt([1.2, 3.4, 9.6]) // [1, 3, 9]

parseInt 不同,下面的结果会返回浮点数或指数 :

['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]

使用 map 重新格式化数组中的对象

原理

var kvArray = [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}]

var reformattedArray = kvArray.map(function(obj) {
var rObj = {};
rObj[obj.key] = obj.value;
return rObj;
});
// [{1: 10}, {2: 20}, {3: 30}],

封装

var kvArray = [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}]

kvArrayToObjArray = (obj) => obj.map(e => {
var rArr = [];
rArr.push(e.key, e.value);
return rArr;
}) var reformattedArray = kvArrayToObjArray(kvArray)
// [[1, 10], [2, 20], [3, 30]]

反转字符串

原理

var str = 'Hello';
Array.prototype.map.call(str, function(x) {
return x;
}).reverse().join(''); // 'olleH'

封装

const reverseStr = str => Array.prototype.map.call(str, e => e).reverse().join('')
c = reverseStr('Hello') // 'olleH'

当然,还有一个更简单的反转字符串方法,使用 ES6 的解构即可

const reverseString = str => [...str].reverse().join('');

reverseString('foobar') // 'raboof'

将字符串转换为 ASCII 码

原理

var a = Array.prototype.map.call("Hello World", function(x) {
return x.charCodeAt(0);
})
// [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

封装

const strToAscii = str => Array.prototype.map.call(str, e => e.charCodeAt(0))
strToAscii("Hello World") // [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]

DOM 操作

甚至可以使用 map 对 DOM 进行操作

var elems = document.querySelectorAll('select option:checked');
var values = Array.prototype.map.call(elems, function(obj) {
return obj.value;
});

深入理解 Array.prototype.map()的更多相关文章

  1. Javascript中Array.prototype.map()详解

    map 方法会给原数组中的每个元素都按顺序调用一次 callback 函数.callback 每次执行后的返回值组合起来形成一个新数组. callback 函数只会在有值的索引上被调用:那些从来没被赋 ...

  2. Array.prototype.map()详解

    今天在地铁上看到这样一个小例子: ["1","2","3"].map(parseInt); 相信很多人和我一样,觉得输出的结果是[1,2,3 ...

  3. js 数组map用法 Array.prototype.map()

    map 这里的map不是"地图"的意思,而是指"映射".[].map(); 基本用法跟forEach方法类似: array.map(callback,[ thi ...

  4. Array.prototype.map()

    mdn上解释的特别详细 概述 map() 方法返回一个由原数组中的每个元素调用一个指定方法后的返回值组成的新数组. 语法 array.map(callback[, thisArg]) 参数 callb ...

  5. Array.prototype.map()和Array.prototypefilter()

    ES5 => 筛选功能  Array.prototypefilter(): 代码: var words = ['spray', 'limit', 'elite', 'exuberant', 'd ...

  6. javascript的Array.prototype.map()和jQuery的jQuery.map()

    两个方法都可以根据现有数组创建新数组,但在使用过程中发现有些不同之处 以下面这个数据为例: var numbers = [1, 3, 4, 6, 9]; 1. 对undefined和null的处理 a ...

  7. Array.prototype.map()方法详解

    Array.prototype.map() 1 语法 const new_array = arr.map(callback[, thisArg]) 2 简单栗子 let arr = [1, 5, 10 ...

  8. javascript 一些函数的实现 Function.prototype.bind, Array.prototype.map

    * Function.prototype.bind Function.prototype.bind = function() { var self = this, context = [].shift ...

  9. 理解Array.prototype.slice.call(arguments)

    在很多时候经常看到Array.prototype.slice.call()方法,比如Array.prototype.slice.call(arguments),下面讲一下其原理: 1.基本讲解 1.在 ...

随机推荐

  1. IP分片丢失重传 - Sacrifice的日志 - 网易博客

        尽管IP分片看起来是是透明的,但有一点让人不想使用它:即使只丢失一片数据也要重传整个数据报.为什么会发生这种情况呢?     因为IP层本身没有超时重传的机制--由更高层来负责超时和重传(TC ...

  2. UML和模式应用4:初始阶段(6)--迭代方法中如何使用用例

    1.前言 用例是UP和其他众多迭代方法的核心.UP提倡用例驱动开发. 2. 迭代方法中如何使用用例 功能需求首先定义在用例中 用例是迭代计划的重要部分,迭代是通过选择一些用例场景或整个用例来定义的 用 ...

  3. centos6中iptables单机网络防火墙的使用

    概述: iptables:基于软件的形式实现的一种防火墙的软件程序 Firewall:工作在主机或网络边缘,对进出的报文按事先定义的规则进行检查,并且由匹配到的规则进行处理的一组硬件或软件,甚至可能是 ...

  4. Ex 6_19 至多用k枚硬币兑换价格_第七次作业

    子问题定义: 定义一个二维数组b,其中b[i][j]表示用i个硬币是否能兑换价格j,表示第i个币种的面值, 递归关系: 初值设定: 求解顺序: 按下标从小到大依次求解数组b每一列的值,最后二维数组b的 ...

  5. Expm 7_2区间调度问题

    [问题描述] 给定n个活动,其中的每个活动ai包含一个起始时间si与结束时间fi.设计与实现算法从n个活动中找出一个最大的相互兼容的活动子集S. 要求:分别设计动态规划与贪心算法求解该问题.其中,对贪 ...

  6. 通过使用CSS字体阴影效果解决hover图片时显示文字看不清的问题

    1.前言 最近需要加入一个小功能,在鼠标越过图片时,提示其大小和分辨率,而不想用增加属性title来提醒,不够好看.然而发现如果文字是一种颜色,然后总有概率碰到那张图上浮一层的文字会看不到,所以加入文 ...

  7. 破解idea

    2019最新注册码 地址:  http://idea.lanyus.com/ https://blog.csdn.net/best_luxi/article/details/81479820

  8. CBAM: 卷积块注意模块

    CBAM: Convolutional Block Attention Module 论文地址:https://arxiv.org/abs/1807.06521   简介:我们提出了卷积块注意模块 ( ...

  9. django----数据库操作(对model增删改查)

    优化查询 articles_list=models.Article.objects.all().iterator() for i in articles_list: print(i.title) 添加 ...

  10. 步步为营-59-svn简介

    说明:版本控制器Svn的使用,安装教程不再多说 VisualSVN-Server--项目经理 TortoiseSVN--右击的时候显示 VisualSVN-- visual studio中使用 1 搭 ...