深入理解 Array.prototype.map()

map() 方法創(chuàng)建一個(gè)新數(shù)組,其結(jié)果是該數(shù)組中的每個(gè)元素都調(diào)用一個(gè)提供的函數(shù)后返回的結(jié)果。

語法

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

參數(shù)

  • callback 生成新數(shù)組元素的函數(shù),使用三個(gè)參數(shù):
    • currentValue 數(shù)組中正在處理的當(dāng)前元素。
    • index 數(shù)組中正在處理的當(dāng)前元素的索引。
    • array map 方法被調(diào)用的數(shù)組。
  • thisArg 可選的。執(zhí)行 callback 函數(shù)時(shí) 使用的this 值。

實(shí)際應(yīng)用

使用指定的方法對(duì)數(shù)組做批處理

原理

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]

只需要傳入對(duì)應(yīng)的處理方法,即可對(duì)數(shù)組所有元素做批處理。

當(dāng)然也可對(duì)此方法進(jìn)行二次封裝:

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) // 求倍數(shù)

arrToSquare(numbers) // [1, 16, 81]
arrToSqrt(numbers) // [1, 2, 3]

多參數(shù)函數(shù)批量轉(zhuǎn)化的誤區(qū)

先看下面一個(gè)方法:

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

第一反應(yīng),這里應(yīng)該返回的是 [1, 2, 3],然而,實(shí)際上返回的卻是 [1, NaN, NaN]。

這是為什么呢?

事實(shí)上,parseInt 接收兩個(gè)參數(shù),第一個(gè)是原始值,第二個(gè)是進(jìn)制值,通常我們使用 parseInt('5') 類似的操作,實(shí)際上是默認(rèn)第二參數(shù)為 10,。但注意,在 map 回調(diào)函數(shù)中,有三個(gè)參數(shù),第一個(gè)是遍歷出來的每一個(gè)元素,第二參數(shù)為遍歷出的元素的下標(biāo),第三參數(shù)為調(diào)用者本身。這里, parseInt 接到了 map 的前兩個(gè)參數(shù),也就是元素和下標(biāo),第三參數(shù)被忽略,parseInt 把傳過來的索引值當(dāng)成進(jìn)制數(shù)來使用,從而返回了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 不同,下面的結(jié)果會(huì)返回浮點(diǎn)數(shù)或指數(shù) :

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

使用 map 重新格式化數(shù)組中的對(duì)象

原理

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]]

反轉(zhuǎn)字符串

原理

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'

當(dāng)然,還有一個(gè)更簡單的反轉(zhuǎn)字符串方法,使用 ES6 的解構(gòu)即可

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

reverseString('foobar') // 'raboof'

將字符串轉(zhuǎn)換為 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 對(duì) DOM 進(jìn)行操作

var elems = document.querySelectorAll('select option:checked');
var values = Array.prototype.map.call(elems, function(obj) {
  return obj.value;
});
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容