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

166 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><strong><code>for...in</code>语句</strong>以任意顺序遍历一个对象的<a href="Enumerability_and_ownership_of_properties">可枚举属性</a>。对于每个不同的属性,语句都会被执行。</p>
<h2 id="Syntax" name="Syntax">语法</h2>
<pre><code class="language-javascript">for (<var>variable</var> in <var>object</var>) {<em>...</em>}
</code></pre>
<dl>
<dt><code>variable</code></dt>
<dd>在每次迭代时,将不同的属性名分配给<em>变量</em></dd>
</dl>
<dl>
<dt><code>object</code></dt>
<dd>被迭代枚举其属性的对象。</dd>
</dl>
<h2 id="描述">描述</h2>
<p><code>for...in</code> 循环只遍历可枚举属性。像 <code>Array</code><code>Object</code>使用内置构造函数所创建的对象都会继承自<code>Object.prototype</code><code>String.prototype</code>的不可枚举属性,例如 <a href="Reference/String" title="此页面仍未被本地化, 期待您的翻译!"><code>String</code></a> 的 <a href="Reference/Global_Objects/String/indexOf" title="indexOf() 方法返回调用  String 对象中第一次出现的指定值的索引开始在 fromIndex进行搜索。"><code>indexOf()</code></a>  方法或 <a href="Reference/Global_Objects/Object" title="Object 构造函数创建一个对象包装器。"><code>Object</code></a><a href="Reference/Global_Objects/Object/toString" title="toString() 方法返回一个表示该对象的字符串。"><code>toString()</code></a>方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。</p>
<h4 id="删除,添加或者修改属性">删除,添加或者修改属性</h4>
<p><code>for...in</code> 循环以任意序迭代一个对象的属性(请参阅<a href="Reference/Operators/delete" title="delete 操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放。"><code>delete</code></a>运算符,了解为什么不能依赖于迭代的表面有序性,至少在跨浏览器设置中)。如果一个属性在一次迭代中被修改,在稍后被访问,其在循环中的值是其在稍后时间的值。一个在被访问之前已经被删除的属性将不会在之后被访问。在迭代进行时被添加到对象的属性,可能在之后的迭代被访问,也可能被忽略。</p>
<p>通常,在迭代过程中最好不要在对象上进行添加、修改或者删除属性的操作,除非是对当前正在被访问的属性。这里并不保证是否一个被添加的属性在迭代过程中会被访问到,不保证一个修改后的属性(除非是正在被访问的)会在修改前或者修改后被访问,不保证一个被删除的属性将会在它被删除之前被访问。</p>
<h3 id="数组迭代和_for...in" style="line-height: 24px; font-size: 1.71428571428571rem;">数组迭代和 <code>for...in</code></h3>
<div class="note">
<p><strong>提示:</strong><code>for...in</code>不应该用于迭代一个 <a href="Reference/Array" title="REDIRECT Array"><code>Array</code></a>,其中索引顺序很重要。</p>
</div>
<p>数组索引只是具有整数名称的枚举属性,并且与通用对象属性相同。不能保证<code>for ... in</code>将以任何特定的顺序返回索引。<code>for ... in</code>循环语句将返回所有可枚举属性,包括非整数类型的名称和继承的那些。</p>
<p>因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行<a href="Reference/Statements/for" title="for 语句用于创建一个循环,它包含了三个可选的表达式,三个可选的表达式包围在圆括号中并由分号分隔, 后跟一个在循环中执行的语句(通常是一个块语句)。"><code>for</code></a>循环(或者使用 <a href="Reference/Global_Objects/Array/forEach" title="forEach() 方法对数组的每个元素执行一次提供的函数。"><code>Array.prototype.forEach()</code></a><a href="Reference/Statements/for...of" title="for...of语句在可迭代对象包括 ArrayMapSetStringTypedArrayarguments 对象等等上创建一个迭代循环调用自定义迭代钩子并为每个不同属性的值执行语句"><code>for...of</code></a> 循环)。</p>
<h3 id="仅迭代自身的属性" style="line-height: 24px; font-size: 1.71428571428571rem;">仅迭代自身的属性</h3>
<p>如果你只要考虑对象本身的属性,而不是它的原型,那么使用 <a href="Reference/Global_Objects/Object/getOwnPropertyNames" title="Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名包括不可枚举属性但不包括Symbol值作为名称的属性组成的数组。"><code>getOwnPropertyNames()</code></a> 或执行 <a href="Reference/Global_Objects/Object/hasOwnProperty" title="hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性"><code>hasOwnProperty()</code></a> 来确定某属性是否是对象本身的属性(也能使用<a href="Reference/Global_Objects/Object/propertyIsEnumerable" title="propertyIsEnumerable() 方法返回一个布尔值,表示指定的属性是否可枚举。"><code>propertyIsEnumerable</code></a>)。或者,如果你知道不会有任何外部代码干扰,您可以使用检查方法扩展内置原型。</p>
<h2 id="Example" name="Example">示例</h2>
<p>下面的函数接受一个对象作为参数。被调用时迭代传入对象的所有可枚举属性然后返回一个所有属性名和其对应值的字符串。</p>
<pre><code class="language-javascript">var obj = {a:1, b:2, c:3};
for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
}
// Output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"</code></pre>
<p>下面的函数说明了<a href="Reference/Global_Objects/Object/hasOwnProperty" title="hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性"><code>hasOwnProperty()</code></a>的用法:继承的属性不显示。</p>
<pre><code class="language-javascript">var triangle = {a: 1, b: 2, c: 3};
function ColoredTriangle() {
this.color = 'red';
}
ColoredTriangle.prototype = triangle;
var obj = new ColoredTriangle();
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(`obj.${prop} = ${obj[prop]}`);
}
}
// Output:
// "obj.color = red"</code></pre>
<h2 id="规范">规范</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://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">for...in statement</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">for...in statement</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/5.1/#sec-12.6.4" hreflang="en" lang="en" rel="noopener">ECMAScript 5.1 (ECMA-262)<br/><small lang="zh-CN">for...in statement</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf#sec-12.6.4" hreflang="en" lang="en" rel="noopener">ECMAScript 3rd Edition (ECMA-262)<br/><small lang="zh-CN">for...in statement</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf#sec-12.6.3" hreflang="en" lang="en" rel="noopener">ECMAScript 1st Edition (ECMA-262)<br/><small lang="zh-CN">for...in statement</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition.</td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容">浏览器兼容</h2>
<div class="hidden">The compatibility table on 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>for...in</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>
Yes</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</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>
6</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>
<h2 id="兼容性:初始化函数表达式">兼容性:初始化函数表达式</h2>
<p>在 SpiderMonkey 40 (Firefox 40 / Thunderbird 40 / SeaMonkey 2.37) 版本之前,可以在使用一个初始化表达式(<code>i=0</code>)在一个<code>for...in</code>循环中:</p>
<pre><code class="language-js example-bad">var obj = {a: 1, b: 2, c: 3};
for (var i = 0 in obj) {
console.log(obj[i]);
}
// 1
// 2
// 3
</code></pre>
<p><span style="line-height: 1.5;">这个非标准行为现在在版本40及更高版本中被忽略并将在严格模式<a class="external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=748550" rel="noopener" title="FIXED: Remove InitialiserNoIn[opt] from ... in for(var ... in obj) to help simplify ES6">bug 748550</a> 和 </span><a class="external" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1164741" rel="noopener" title="FIXED: Add back partial support for |for (var i = 0 in obj);| syntax, ignoring the initializer rather than failing on it">bug 1164741</a><span style="line-height: 1.5;">中呈现<a href="Reference/Global_Objects/SyntaxError" title="SyntaxError 对象代表尝试解析语法上不合法的代码的错误。"><code>SyntaxError</code></a>"<a href="Reference/Errors/Invalid_for-in_initializer">for-in loop head declarations may not have initializers</a>")错误。</span></p>
<p><span style="line-height: 1.5;">像其他引擎 V8(Chrome)</span>Chakra (IE/Edge) JSC (WebKit/Safari) 正在研究去除这种不标准的行为。</p>
<h2 id="相关链接">相关链接</h2>
<ul>
<li><a href="Reference/Statements/for...of" title="for...of语句在可迭代对象包括 ArrayMapSetStringTypedArrayarguments 对象等等上创建一个迭代循环调用自定义迭代钩子并为每个不同属性的值执行语句"><code>for...of</code></a>  一个类似的迭代属性值的语句</li>
<li><a href="Reference/Statements/for_each...in" title="使用一个变量迭代一个对象的所有属性值,对于每一个属性值,有一个指定的语句块被执行."><code>for each in</code></a> 一个类似的但是迭代的是对象的属性的值而不是其属性名字的语句(过时的)</li>
<li><a href="Reference/Statements/for" title="for 语句用于创建一个循环,它包含了三个可选的表达式,三个可选的表达式包围在圆括号中并由分号分隔, 后跟一个在循环中执行的语句(通常是一个块语句)。"><code>for</code></a></li>
<li>迭代器和构造器uses the <code>for...in</code> syntax</li>
<li><a href="Enumerability_and_ownership_of_properties">属性的可枚举性和所有权</a></li>
<li><a href="Reference/Global_Objects/Object/getOwnPropertyNames" title="Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名包括不可枚举属性但不包括Symbol值作为名称的属性组成的数组。"><code>Object.getOwnPropertyNames()</code></a></li>
<li><a href="Reference/Global_Objects/Object/hasOwnProperty" title="hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性"><code>Object.prototype.hasOwnProperty()</code></a></li>
<li><a href="Reference/Global_Objects/Array/forEach" title="forEach() 方法对数组的每个元素执行一次提供的函数。"><code>Array.prototype.forEach()</code></a></li>
</ul>
</article>