map()
方法返回一個由原數組中的每個元素調用一個指定方法后的返回值組成的新數組。
語法
array.map(callback[, 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 is now [{1:10}, {2:20}, {3:30}],
// kvArray is still [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}]
將數組中的單詞轉換成對應的復數形式.
下面的代碼將一個數組中的所有單詞轉換成對應的復數形式.
function fuzzyPlural(single) { var result = single.replace(/o/g, 'e'); if( single === 'kangaroo'){ result += 'se'; } return result; } var words = ["foot", "goose", "moose", "kangaroo"]; console.log(words.map(fuzzyPlural)); // ["feet", "geese", "meese", "kangareese"]
一般的 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('');
// Output: '54321'
// Bonus: use '===' to test if original string was a palindrome
使用技巧案例
通常情況下,map
方法中的 callback
函數只需要接受一個參數,就是正在被遍歷的數組元素本身。但這並不意味着 map
只給 callback
傳了一個參數。這個思維慣性可能會讓我們犯一個很容易犯的錯誤。
// 下面的語句返回什么呢: ["1", "2", "3"].map(parseInt); // 你可能覺的會是[1, 2, 3] // 但實際的結果是 [1, NaN, NaN] // 通常使用parseInt時,只需要傳遞一個參數. // 但實際上,parseInt可以有兩個參數.第二個參數是進制數. // 可以通過語句"alert(parseInt.length)===2"來驗證. // map方法在調用callback函數時,會給它傳遞三個參數:當前正在遍歷的元素, // 元素索引, 原數組本身. // 第三個參數parseInt會忽視, 但第二個參數不會,也就是說, // parseInt把傳過來的索引值當成進制數來使用.從而返回了NaN. /* //應該使用如下的用戶函數returnInt function returnInt(element){ return parseInt(element,10); } ["1", "2", "3"].map(returnInt); // 返回[1,2,3] */
兼容舊環境(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; }; }
規范
Specification | Status | Comment |
---|---|---|
ECMAScript 5.1 (ECMA-262) Array.prototype.map |
Standard | Initial definition. Implemented in JavaScript 1.6 |
ECMAScript 2015 (6th Edition, ECMA-262) Array.prototype.map |
Standard | |
ECMAScript 2017 Draft (ECMA-262) Array.prototype.map |
Draft |
瀏覽器兼容性
Feature | Firefox (Gecko) | Chrome | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
Basic support | (Yes) | 1.5 (1.8) | 9 | (Yes) | (Yes) |