深入了解 Array.prototype.map()
map()
方法建立一個新數組,其結果是該數組中的每個元素都調用一個提供的函數後傳回的結果。
文法
let new_array = arr.map(function callback(currentValue, index, array) {
// Return element for new_array
}[, thisArg])
參數
-
生成新數組元素的函數,使用三個參數:callback
-
數組中正在處理的目前元素。currentValue
-
數組中正在處理的目前元素的索引。index
-
map 方法被調用的數組。array
-
-
可選的。執行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;
});