`map()` 方法创建一个新数组，其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone https://github.com/mdn/interactive-examples and send us a pull request.

## 语法

    var new_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的工作方式。当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;
    });

### 使用技巧案例

(原文地址)

通常情况下，`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.

    function returnInt(element) {
      return parseInt(element, 10);
    }

    ['1', '2', '3'].map(returnInt); // [1, 2, 3]
    // 意料之中的结果

    // 也可以使用简单的箭头函数，结果同上
    ['1', '2', '3'].map( str => parseInt(str) );

    // 一个更简单的方式:
    ['1', '2', '3'].map(Number); // [1, 2, 3]
    // 与`parseInt` 不同，下面的结果会返回浮点数或指数:
    ['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]

## 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 Latest Draft (ECMA-262) Array.prototype.map | Draft |

## 浏览器兼容性

The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out https://github.com/mdn/browser-compat-data and send us a pull request.

Update compatibility data on GitHub

| Desktop | Mobile | Server
| Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | Android webview | Chrome for Android | Edge Mobile | Firefox for Android | Opera for Android | Safari on iOS | Samsung Internet | Node.js
`map` | Chrome Full support Yes | Edge Full support 12 | Firefox Full support 1.5 | IE Full support 9 | Opera Full support Yes | Safari Full support Yes | WebView Android Full support Yes | Chrome Android Full support Yes | Edge Mobile Full support Yes | Firefox Android Full support 4 | Opera Android Full support Yes | Safari iOS Full support Yes | Samsung Internet Android Full support Yes | nodejs Full support Yes

### Legend

Full support
  Full support

## 相关链接

- `Array.prototype.forEach()`
- `Map` object
- `Array.from()`