aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/statements/for...in/index.html
blob: ed5418373210fc57393d780728592dd6719f0bc9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
---
title: for...in
slug: Web/JavaScript/Reference/Statements/for...in
tags:
  - JavaScript
  - Statement
translation_of: Web/JavaScript/Reference/Statements/for...in
---
<div>{{jsSidebar("Statements")}}</div>

<p><strong><code>for...in</code>语句</strong>以任意顺序遍历一个对象的除<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol">Symbol</a>以外的<a href="/zh-CN/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">可枚举</a>属性,包括继承的可枚举属性。</p>

<h2 id="Syntax">语法</h2>

<pre>for (<var>variable</var> in <var>object</var>)
  statement</pre>

<dl>
 <dt><code>variable</code></dt>
 <dd>在每次迭代时,variable会被赋值为不同的属性名。</dd>
 <dt><code>object</code></dt>
 <dd>非Symbol类型的可枚举属性被迭代的对象。</dd>
</dl>

<h2 id="sect1"></h2>

<h3 id="数组迭代和_for...in">数组迭代和 <code>for...in</code></h3>

<div class="note">
<p><strong>备注:</strong><code>for...in</code>不应该用于迭代一个关注索引顺序的 {{jsxref("Array")}}。</p>
</div>

<h3 id="仅迭代自身的属性">仅迭代自身的属性</h3>

<p>如果你只要考虑对象本身的属性,而不是它的原型,那么使用 {{jsxref("Object.getOwnPropertyNames", "getOwnPropertyNames()")}} 或执行 {{jsxref("Object.prototype.hasOwnProperty", "hasOwnProperty()")}} 来确定某属性是否是对象本身的属性(也能使用{{jsxref("Object.prototype.propertyIsEnumerable", "propertyIsEnumerable")}})。或者,如果你知道不会有任何外部代码干扰,您可以使用检查方法扩展内置原型。</p>

<h2 id="Example">为什么用for ... in?</h2>

<p><code>for ... in</code>是为遍历对象属性而构建的,不建议与数组一起使用,数组可以用<code>Array.prototype.forEach()</code><code>for ... of</code>,那么<code>for ... in</code>的到底有什么用呢?</p>

<p>它最常用的地方应该是用于调试,可以更方便的去检查对象属性(通过输出到控制台或其他方式)。尽管对于处理存储数据,数组更实用些,但是你在处理有<code>key-value</code>数据(比如属性用作“键”),需要检查其中的任何键是否为某值的情况时,还是推荐用<code>for ... in</code></p>

<h2 id="Example">示例</h2>

<p>下面的函数接受一个对象作为参数。被调用时迭代传入对象的所有可枚举属性然后返回一个所有属性名和其对应值的字符串。</p>

<pre class="brush: js">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"</pre>

<p>下面的函数说明了{{jsxref("Object.prototype.hasOwnProperty", "hasOwnProperty()")}}的用法:继承的属性不显示。</p>

<pre class="brush: js">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"</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>{{SpecName('ESDraft', '#sec-for-in-and-for-of-statements', 'for...in statement')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-for-in-and-for-of-statements', 'for...in statement')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-12.6.4', 'for...in statement')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ES3', '#sec-12.6.4', 'for...in statement')}}</td>
   <td>{{Spec2('ES3')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ES1', '#sec-12.6.3', 'for...in statement')}}</td>
   <td>{{Spec2('ES1')}}</td>
   <td>Initial definition.</td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容">浏览器兼容</h2>

<p>{{Compat("javascript.statements.for_in")}}</p>

<h2 id="兼容性:初始化函数表达式">兼容性:初始化函数表达式</h2>

<p>在 SpiderMonkey 40 {{geckoRelease(40)}} 版本之前,可以在使用一个初始化表达式(<code>i=0</code>)在一个<code>for...in</code>循环中:</p>

<pre class="brush: js example-bad">var obj = {a: 1, b: 2, c: 3};
for (var i = 0 in obj) {
  console.log(obj[i]);
}
// 1
// 2
// 3
</pre>

<p>这个非标准行为现在在版本40及更高版本中被忽略,并将在严格模式({{bug(748550)}} 和 {{bug(1164741)}})中呈现{{jsxref("SyntaxError")}}("<a href="/zh-CN/docs/Web/JavaScript/Reference/Errors/Invalid_for-in_initializer">for-in loop head declarations may not have initializers</a>")错误。</p>

<p>像其他引擎 V8(Chrome),Chakra (IE/Edge), JSC (WebKit/Safari) 正在研究去除这种不标准的行为。</p>

<h2 id="相关链接">相关链接</h2>

<ul>
 <li>{{jsxref("Statements/for...of", "for...of")}}  一个类似的迭代属性值的语句</li>
 <li>{{jsxref("Statements/for_each...in", "for each in")}} 一个类似的但是迭代的是对象的属性的值而不是其属性名字的语句(过时的)</li>
 <li>{{jsxref("Statements/for", "for")}}</li>
 <li>迭代器和构造器(uses the <code>for...in</code> syntax)</li>
 <li><a href="/zh-CN/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">属性的可枚举性和所有权</a></li>
 <li>{{jsxref("Object.getOwnPropertyNames()")}}</li>
 <li>{{jsxref("Object.prototype.hasOwnProperty()")}}</li>
 <li>{{jsxref("Array.prototype.forEach()")}}</li>
</ul>