天天看点

深入理解 Array.prototype.map()深入理解 Array.prototype.map()

深入理解 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 = [, , ];
var roots = numbers.map(Math.sqrt);
console.log(numbers) // [1, 4, 9]
console.log(roots) // [1, 2, 3]
           

封装

var numbers = [, , ];
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 = [, , ];

const arrBat = (arr, func) => arr.map(func)
const arrToSqrt = (arr) => arrBat(arr, Math.sqrt) // 开平方根
const arrToSquare = (arr) => arrBat(arr, e => Math.pow(e, )) // 平方
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 =>  * 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, ))
arrToInt("57832") // [5, 7, 8, 3, 2]
arrToInt([, , ]) // [1, 3, 9]
           

parseInt

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

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

原理

var kvArray = [{key: , value: }, {key: , value: }, {key: , value: }]

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

封装

var kvArray = [{key: , value: }, {key: , value: }, {key: , value: }]

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(); 
})
// [72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
           

封装

const strToAscii = str => Array.prototype.map.call(str, e => e.charCodeAt())
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;
});
           

继续阅读