map() 方法創建一個新數組,其結果是該數組中的每個元素都調用一個提供的函數後返回的結果。
let numbers = [1, 5, 10, 15];
let doubles = numbers.map((x) => {
return x * 2;
});
// doubles is now [2, 10, 20, 30]
// numbers is still [1, 5, 10, 15]
let numbers = [1, 4, 9];
let roots = numbers.map(Math.sqrt);
// roots is now [1, 2, 3]
// numbers is still [1, 4, 9]
語法
let array = arr.map(function callback(currentValue, index, array) {
// Return element for new_array
}[, thisArg])
參數
callback
生成新數組元素的函數,使用三個參數:
currentValue
callback 的第一個參數,數組中正在處理的當前元素。
index
callback 的第二個參數,數組中正在處理的當前元素的索引。
array
callback 的第三個參數,map 方法被調用的數組。
thisArg
可選的。執行 callback 函數時 使用的this 值。
返回值
一個新數組,每個元素都是回調函數的結果。
描述
map 方法會給原數組中的每個元素都按順序調用一次 callback 函數。callback 每次執行後的返回值(包括 undefined)組合起來形成一個新數組。 callback 函數只會在有值的索引上被調用;那些從來沒被賦過值或者使用 delete 刪除的索引則不會被調用。
callback 函數會被自動傳入三個參數:數組元素,元素索引,原數組本身。
如果 thisArg 參數有值,則每次 callback 函數被調用的時候,this 都會指向 thisArg 參數上的這個對象。如果省略了 thisArg 參數,或者賦值爲 null 或 undefined,則 this 指向全局對象 。
map 不修改調用它的原數組本身(當然可以在 callback 執行時改變原數組)。
使用 map 方法處理數組時,數組元素的範圍是在 callback 方法第一次調用之前就已經確定了。在 map 方法執行的過程中:原數組中新增加的元素將不會被 callback 訪問到;若已經存在的元素被改變或刪除了,則它們的傳遞到 callback 的值是 map 方法遍歷到它們的那一時刻的值;而被刪除的元素將不會被訪問到。
示例
求數組中每個元素的平方根
下面的代碼創建了一個新數組,值爲原數組中對應數字的平方根。
var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots的值爲[1, 2, 3], numbers的值仍爲[1, 4, 9]
使用 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;
});
// reformattedArray 數組爲: [{1: 10}, {2: 20}, {3: 30}],
// kvArray 數組未被修改:
// [{key: 1, value: 10},
// {key: 2, value: 20},
// {key: 3, value: 30}]
用一個僅有一個參數的函數來mapping一個數字數組
下面的代碼表示了當函數需要一個參數時map的工作方式。這個參數會遍歷原始數組中的元素。
var numbers = [1, 4, 9]; var doubles = numbers.map(function(num) {
return num * 2; });// doubles數組的值爲: [2, 8, 18] // numbers數組未被修改: [1, 4, 9]
一般的 map 方法
下面的例子演示如何在一個 String 上使用 map 方法獲取字符串中每個字符所對應的 ASCII 碼組成的數組:
var map = Array.prototype.map
var a = map.call("Hello World", function(x) {
return x.charCodeAt(0);
})
// a的值爲[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]
querySelectorAll 應用
下面代碼展示瞭如何去遍歷用 querySelectorAll 得到的動態對象集合。在這裏,我們獲得了文檔裏所有選中的選項,並將其打印:
var elems = document.querySelectorAll('select option:checked');
var values = Array.prototype.map.call(elems, function(obj) {
return obj.value;
});
反轉字符串
var str = '12345';
Array.prototype.map.call(str, function(x) {
return x;
}).reverse().join('');
// 輸出: '54321'
// Bonus: use '===' to test if original string was a palindrome
使用技巧案例
通常情況下,map 方法中的 callback 函數只需要接受一個參數,就是正在被遍歷的數組元素本身。但這並不意味着 map 只給 callback 傳了一個參數。這個思維慣性可能會讓我們犯一個很容易犯的錯誤。
兼容舊環境(Polyfill)
map 是在最近的 ECMA-262 標準中新添加的方法;所以一些舊版本的瀏覽器可能沒有實現該方法。在那些沒有原生支持 map 方法的瀏覽器中,你可以使用下面的 Javascript 代碼來實現它。所使用的算法正是 ECMA-262,第 5 版規定的。假定Object, TypeError, 和 Array 有他們的原始值。而且 callback.call 的原始值也是 Function.prototype.call
// 實現 ECMA-262, Edition 5, 15.4.4.19
// 參考: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. 將O賦值爲調用map方法的數組.
var O = Object(this);
// 2.將len賦值爲數組O的長度.
var len = O.length >>> 0;
// 3.如果callback不是函數,則拋出TypeError異常.
if (Object.prototype.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}
// 4. 如果參數thisArg有值,則將T賦值爲thisArg;否則T爲undefined.
if (thisArg) {
T = thisArg;
}
// 5. 創建新數組A,長度爲原數組O長度len
A = new Array(len);
// 6. 將k賦值爲0
k = 0;
// 7. 當 k < len 時,執行循環.
while(k < len) {
var kValue, mappedValue;
//遍歷O,k爲原數組索引
if (k in O) {
//kValue爲索引k對應的值.
kValue = O[ k ];
// 執行callback,this指向T,參數有三個.分別是kValue:值,k:索引,O:原數組.
mappedValue = callback.call(T, kValue, k, O);
// 返回值添加到新數組A中.
A[ k ] = mappedValue;
}
// k自增1
k++;
}
// 8. 返回新數組A
return A;
};
}
瀏覽器兼容性
本文引自:[mozillla(https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map)