2019-04-21 11:50:48 +08:00

257 lines
18 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<article id="wikiArticle">
<div></div>
<p><code><strong>map()</strong></code> 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。</p>
<div><iframe class="interactive interactive-js" frameborder="0" height="250" src="https://interactive-examples.mdn.mozilla.net/pages/js/array-map.html" width="100%"></iframe></div>
<p class="hidden">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 <a class="external" href="https://github.com/mdn/interactive-examples" rel="noopener">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p>
<h2 id="Syntax" name="Syntax">语法</h2>
<pre><var>var new_array = arr</var>.map(function <var>callback(currentValue[, index[, array]]) {
// Return element for new_array </var>
<var>}</var>[, <var>thisArg</var>])</code></pre>
<h3 id="Parameters" name="Parameters">参数</h3>
<dl>
<dt><code>callback</code></dt>
<dd>生成新数组元素的函数,使用三个参数:
<dl>
<dt><code>currentValue</code></dt>
<dd><code>callback</code> 数组中正在处理的当前元素。</dd>
<dt><code>index</code><span class="inlineIndicator optional optionalInline">可选</span></dt>
<dd><code>callback</code> 数组中正在处理的当前元素的索引。</dd>
<dt><code>array</code><span class="inlineIndicator optional optionalInline">可选</span></dt>
<dd><code>callback</code>  <code>map</code> 方法被调用的数组。</dd>
</dl>
</dd>
<dt><code>thisArg</code><span class="inlineIndicator optional optionalInline">可选</span></dt>
<dd>执行 <code>callback</code> 函数时使用的<code>this</code> 值。</dd>
</dl>
<h3 id="返回值">返回值</h3>
<p>一个新数组,每个元素都是回调函数的结果。</p>
<h2 id="Description" name="Description">描述</h2>
<p><code>map</code> 方法会给原数组中的每个元素都按顺序调用一次  <code>callback</code> 函数。<code>callback</code> 每次执行后的返回值(包括 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a>)组合起来形成一个新数组。 <code>callback</code> 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 <code>delete</code> 删除的索引则不会被调用。</p>
<p><code>callback</code> 函数会被自动传入三个参数:数组元素,元素索引,原数组本身。</p>
<p>如果 <code>thisArg</code> 参数有值,则每次 <code>callback</code> 函数被调用的时候,<code>this</code> 都会指向 <code>thisArg</code> 参数上的这个对象。如果省略了 <code>thisArg </code><code>参数,</code><code>或者赋值为 null</code><code>undefined</code>,则 this 指向全局对象 。</p>
<p><code>map </code>不修改调用它的原数组本身(当然可以在 <code>callback</code> 执行时改变原数组)。</p>
<p>使用 map 方法处理数组时,数组元素的范围是在 callback 方法第一次调用之前就已经确定了。在 map 方法执行的过程中:原数组中新增加的元素将不会被 callback 访问到;若已经存在的元素被改变或删除了,则它们的传递到 callback 的值是 map 方法遍历到它们的那一时刻的值;而被删除的元素将不会被访问到。</p>
<h2 id="Examples" name="Examples">示例</h2>
<h3 id="Example:_Mapping_an_array_of_numbers_to_an_array_of_square_roots" name="Example:_Mapping_an_array_of_numbers_to_an_array_of_square_roots">求数组中每个元素的平方根</h3>
<p>下面的代码创建了一个新数组,值为原数组中对应数字的平方根。</p>
<pre><code class="language-javascript">var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9]</code></pre>
<h3 id="使用_map_重新格式化数组中的对象">使用 map 重新格式化数组中的对象</h3>
<p>以下代码使用一个包含对象的数组来重新创建一个格式化后的数组。</p>
<pre><code class="language-javascript">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}]
</code></pre>
<h3 id="Example:_Pluralizing_the_words_.28strings.29_in_an_array" name="Example:_Pluralizing_the_words_.28strings.29_in_an_array">使用一个包含一个参数的函数来mapping(构建)一个数字数组</h3>
<p>下面的代码表示了当函数需要一个参数时map的工作方式。当map循环遍历原始数组时这个参数会自动被分配成数组中对应的每个元素。</p>
<pre><code class="language-javascript">var numbers = [1, 4, 9];
var doubles = numbers.map(function(num) {
return num * 2;
});
// doubles数组的值为 [2, 8, 18]
// numbers数组未被修改 [1, 4, 9]</code></pre>
<h3 id="Example:_using_map_generically" name="Example:_using_map_generically">一般的<code>map</code> 方法</h3>
<p>下面的例子演示如何在一个 <a href="Reference/String" title="此页面仍未被本地化, 期待您的翻译!"><code>String</code></a>  上使用 map 方法获取字符串中每个字符所对应的 ASCII 码组成的数组:</p>
<pre><code class="language-javascript">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]
</code></pre>
<h3 id="querySelectorAll_应用"><code>querySelectorAll 应用</code></h3>
<p>下面代码展示了如何去遍历用 <code>querySelectorAll </code>得到的动态对象集合。在这里,我们获得了文档里所有选中的选项,并将其打印:</p>
<pre><code class="language-javascript">var elems = document.querySelectorAll('select option:checked');
var values = Array.prototype.map.call(elems, function(obj) {
return obj.value;
});
</code></pre>
<h3 id="使用技巧案例">使用技巧案例</h3>
<p><a class="external" href="http://www.wirfs-brock.com/allzh-cn/posts/166" rel="noopener">(原文地址)</a></p>
<p>通常情况下,<code>map</code> 方法中的 <code>callback</code> 函数只需要接受一个参数,就是正在被遍历的数组元素本身。但这并不意味着 <code>map</code> 只给 <code>callback</code> 传了一个参数。这个思维惯性可能会让我们犯一个很容易犯的错误。</p>
<pre><code class="language-javascript">// 下面的语句返回什么呢:
["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 =&gt; parseInt(str) );
// 一个更简单的方式:
['1', '2', '3'].map(Number); // [1, 2, 3]
// 与`parseInt` 不同,下面的结果会返回浮点数或指数:
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]
</code></pre>
<h2 id="Compatibility" name="Compatibility" style="line-height: 30px;">Polyfill</h2>
<p><code>map</code> 是在最近的 ECMA-262 标准中新添加的方法;所以一些旧版本的浏览器可能没有实现该方法。在那些没有原生支持 <code>map</code> 方法的浏览器中,你可以使用下面的 Javascript 代码来<code>实现它。</code>所使用的算法正是 ECMA-262第 5 版规定的。假定<code style="color: inherit;">Object</code>, <code style="color: inherit;">TypeError</code>, 和 <code>Array</code> 有他们的原始值。而且 <code style="color: inherit;">callback.call</code> 的原始值也是 <code style="color: inherit;"><a href="/zh-cn/JavaScript/Reference/Global_Objects/Function/call" rel="internal" style="color: rgb(4, 121, 167);">Function.prototype.call</a></code></p>
<pre><code class="language-js" style="font-size: 14px;">// 实现 ECMA-262, Edition 5, 15.4.4.19
// 参考: <a class="external" href="http://es5.github.com/#x15.4.4.19" rel="freelink noopener">http://es5.github.com/#x15.4.4.19</a>
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 &gt;&gt;&gt; 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 &lt; len 时,执行循环.
while(k &lt; 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;
};
}</code></pre>
<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19" hreflang="en" lang="en" rel="noopener">ECMAScript 5.1 (ECMA-262)<br/><small lang="zh-CN">Array.prototype.map</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition.<br/>
Implemented in JavaScript 1.6</td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-array.prototype.map" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">Array.prototype.map</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://tc39.github.io/ecma262/#sec-array.prototype.map" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">Array.prototype.map</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td> </td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容性">浏览器兼容性</h2>
<div>
<div class="hidden">The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a class="external" href="https://github.com/mdn/browser-compat-data" rel="noopener">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div>
<p></p><div class="bc-data"><a class="bc-github-link external" href="https://github.com/mdn/browser-compat-data" rel="noopener">Update compatibility data on GitHub</a><table class="bc-table bc-table-js"><thead><tr class="bc-platforms"><td></td><th class="bc-platform-desktop" colspan="6"><span>Desktop</span></th><th class="bc-platform-mobile" colspan="7"><span>Mobile</span></th><th class="bc-platform-server" colspan="1"><span>Server</span></th></tr><tr class="bc-browsers"><td></td><th class="bc-browser-chrome"><span class="bc-head-txt-label bc-head-icon-chrome">Chrome</span></th><th class="bc-browser-edge"><span class="bc-head-txt-label bc-head-icon-edge">Edge</span></th><th class="bc-browser-firefox"><span class="bc-head-txt-label bc-head-icon-firefox">Firefox</span></th><th class="bc-browser-ie"><span class="bc-head-txt-label bc-head-icon-ie">Internet Explorer</span></th><th class="bc-browser-opera"><span class="bc-head-txt-label bc-head-icon-opera">Opera</span></th><th class="bc-browser-safari"><span class="bc-head-txt-label bc-head-icon-safari">Safari</span></th><th class="bc-browser-webview_android"><span class="bc-head-txt-label bc-head-icon-webview_android">Android webview</span></th><th class="bc-browser-chrome_android"><span class="bc-head-txt-label bc-head-icon-chrome_android">Chrome for Android</span></th><th class="bc-browser-edge_mobile"><span class="bc-head-txt-label bc-head-icon-edge_mobile">Edge Mobile</span></th><th class="bc-browser-firefox_android"><span class="bc-head-txt-label bc-head-icon-firefox_android">Firefox for Android</span></th><th class="bc-browser-opera_android"><span class="bc-head-txt-label bc-head-icon-opera_android">Opera for Android</span></th><th class="bc-browser-safari_ios"><span class="bc-head-txt-label bc-head-icon-safari_ios">Safari on iOS</span></th><th class="bc-browser-samsunginternet_android"><span class="bc-head-txt-label bc-head-icon-samsunginternet_android">Samsung Internet</span></th><th class="bc-browser-nodejs"><span class="bc-head-txt-label bc-head-icon-nodejs">Node.js</span></th></tr></thead><tbody><tr><th scope="row"><code>map</code></th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
12</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
1.5</td><td class="bc-supports-yes bc-browser-ie"><span class="bc-browser-name">IE</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
9</td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-safari"><span class="bc-browser-name">Safari</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
4</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-nodejs"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td></tr></tbody></table><section class="bc-legend" id="sect1"><h3 class="offscreen" id="Legend">Legend</h3><dl><dt><span class="bc-supports-yes bc-supports">
<abbr class="bc-level bc-level-yes only-icon" title="Full support">
<span>Full support</span>
 
</abbr></span></dt><dd>Full support</dd></dl></section></div><p></p>
</div>
<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2>
<ul>
<li><a href="Reference/Global_Objects/Array/forEach" title="forEach() 方法对数组的每个元素执行一次提供的函数。"><code>Array.prototype.forEach()</code></a></li>
<li><a href="Reference/Map" title="此页面仍未被本地化, 期待您的翻译!"><code>Map</code></a> object</li>
<li><a href="Reference/Global_Objects/Array/from" title="Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。"><code>Array.from()</code></a></li>
</ul>
</article>