aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/array/index.html
blob: b8c665f147dc940afd474a21f5b3fe2fc675d312 (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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
---
title: Array
slug: Web/JavaScript/Reference/Global_Objects/Array
tags:
  - JavaScript
  - 二维数组
  - 全局对象
  - 参考手册
  - 数组
translation_of: Web/JavaScript/Reference/Global_Objects/Array
---
<div>{{JSRef}}</div>

<div></div>

<p>JavaScript的 <code><strong>Array</strong></code> 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。</p>

<p><strong>创建数组</strong></p>

<pre class="brush: js">var fruits = ['Apple', 'Banana'];

console.log(fruits.length);
// 2
</pre>

<p><strong>通过索引访问数组元素</strong></p>

<pre class="brush: js">var first = fruits[0];
// Apple

var last = fruits[fruits.length - 1];
// Banana</pre>

<p><strong>遍历数组</strong></p>

<pre class="brush: js">fruits.forEach(function (item, index, array) {
    console.log(item, index);
});
// Apple 0
// Banana 1</pre>

<p><strong>添加元素到数组的末尾</strong></p>

<pre class="brush: js">var newLength = fruits.push('Orange');
// newLength:3; fruits: ["Apple", "Banana", "Orange"]</pre>

<p><strong>删除数组末尾的元素</strong></p>

<pre class="brush: js">var last = fruits.pop(); // remove Orange (from the end)
// last: "Orange"; fruits: ["Apple", "Banana"];</pre>

<p><strong>删除数组最前面(头部)的元素</strong></p>

<pre class="brush: js">var first = fruits.shift(); // remove Apple from the front
// first: "Apple"; fruits: ["Banana"];</pre>

<p><strong>添加元素到数组的头部</strong></p>

<pre class="brush: js">var newLength = fruits.unshift('Strawberry') // add to the front
// ["Strawberry", "Banana"];
</pre>

<p><strong>找出某个元素在数组中的索引</strong></p>

<pre class="brush: js">fruits.push('Mango');
// ["Strawberry", "Banana", "Mango"]

var pos = fruits.indexOf('Banana');
// 1</pre>

<p><strong>通过索引删除某个元素</strong></p>

<pre class="brush: js">var removedItem = fruits.splice(pos, 1); // this is how to remove an item

// ["Strawberry", "Mango"]</pre>

<p><strong>从一个索引位置删除多个元素</strong></p>

<pre class="brush: js">var vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot'];
console.log(vegetables);
// ["Cabbage", "Turnip", "Radish", "Carrot"]

var pos = 1, n = 2;

var removedItems = vegetables.splice(pos, n);
// this is how to remove items, n defines the number of items to be removed,
// from that position(pos) onward to the end of array.

console.log(vegetables);
// ["Cabbage", "Carrot"] (the original array is changed)

console.log(removedItems);
// ["Turnip", "Radish"]</pre>

<p><strong>复制一个数组</strong></p>

<pre class="brush: js">var shallowCopy = fruits.slice(); // this is how to make a copy
// ["Strawberry", "Mango"]</pre>

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

<pre class="syntaxbox">[<var>element0</var>, <var>element1</var>, ..., <var>elementN</var>]
new Array(<var>element0</var>, <var>element1</var>[, ...[, <var>elementN</var>]])
new Array(<var>arrayLength</var>)
</pre>

<dl>
 <dt>
 <h3 id="参数">参数</h3>
 </dt>
 <dt><code>elementN</code></dt>
 <dd><code>Array</code> 构造器会根据给定的元素创建一个 JavaScript 数组,但是当仅有一个参数且为数字时除外(详见下面的 <code>arrayLength</code> 参数)。注意,后面这种情况仅适用于用 <code>Array</code> 构造器创建数组,而不适用于用方括号创建的数组字面量。</dd>
 <dt><code>arrayLength</code></dt>
 <dd>一个范围在 0 到 2<sup>32</sup>-1 之间的整数,此时将返回一个 <code>length</code> 的值等于 <code>arrayLength</code> 的数组对象(言外之意就是该数组此时并没有包含任何实际的元素,不能理所当然地认为它包含 <code>arrayLength</code> 个值为 <code>undefined</code> 的元素)。如果传入的参数不是有效值,则会抛出 {{jsxref("RangeError")}} 异常。</dd>
</dl>

<h2 id="描述">描述</h2>

<p>数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。因为数组的长度可随时改变,并且其数据在内存中也可以不连续,所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。一般来说,数组的这些特性会给使用带来方便,但如果这些特性不适用于你的特定使用场景的话,可以考虑使用类型数组 {{jsxref("TypedArray")}}</p>

<p>只能用整数作为数组元素的索引,而不能用字符串。后者称为<a href="https://en.wikipedia.org/wiki/Associative_array">关联数组</a>。使用非整数并通过<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties">方括号</a><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_Accessors">点号</a>来访问或设置数组元素时,所操作的并不是数组列表中的元素,而是数组对象的<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures#Properties">属性集合</a>上的变量。数组对象的属性和数组元素列表是分开存储的,并且数组的遍历和修改操作也不能作用于这些命名属性。</p>

<h3 id="访问数组元素">访问数组元素</h3>

<p>JavaScript 数组的索引是从0开始的,第一个元素的索引为0,最后一个元素的索引等于该数组的长度减1。如果指定的索引是一个无效值,JavaScript 数组并不会报错,而是会返回 <code>undefined</code></p>

<pre class="brush: js  language-js">var arr = ['this is the first element', 'this is the second element', 'this is the last element'];
console.log(arr[0]);              // 打印 'this is the first element'
console.log(arr[1]);              // 打印 'this is the second element'
console.log(arr[arr.length - 1]); // 打印 'this is the last element'
</pre>

<p>虽然数组元素可以看做是数组对象的属性,就像 <code>toString</code> 一样,但是下面的写法是错误的,运行时会抛出 <code>SyntaxError</code> 异常,而原因则是使用了非法的属性名:</p>

<pre class="brush: js  language-js">console.log(arr.0); // a syntax error
</pre>
<p>并不是 JavaScript 数组有什么特殊之处,而是因为在 JavaScript 中,以数字开头的属性不能用点号引用,必须用方括号。比如,如果一个对象有一个名为 <code>3d</code> 的属性,那么只能用方括号来引用它。下面是具体的例子:</p>

<pre class="brush: js  language-js">var years = [1950, 1960, 1970, 1980, 1990, 2000, 2010];
console.log(years.0);   // 语法错误
console.log(years[0]);  // √
</pre>
<pre class="brush: js  language-js">renderer.3d.setTexture(model, 'character.png');     // 语法错误
renderer['3d'].setTexture(model, 'character.png');  // √
</pre>

<p>注意在 <code>3d</code> 那个例子中,引号是必须的。你也可以将数组的索引用引号引起来,比如 <code>years[2]</code> 可以写成 <code>years['2']</code>。 <code>years[2]</code> 中的 2 会被 JavaScript 解释器通过调用 <code>toString</code> 隐式转换成字符串。正因为这样,<code>'2'</code><code>'02'</code><code>years</code> 中所引用的可能是不同位置上的元素。而下面这个例子也可能会打印 <code>true</code></p>

<pre class="brush: js  language-js">console.log(years['2'] != years['02']);
</pre>
<p>类似地,如果对象的属性名称是保留字(最好不要这么做!),那么就只能通过字符串的形式用方括号来访问(从 firefox 40.0a2 开始也支持用点号访问了):</p>

<pre class="brush: js  language-js">var promise = {
  'var'  : 'text',
  'array': [1, 2, 3, 4]
};

console.log(promise['var']);
</pre>

<h3 id="length_和数字下标之间的关系">length 和数字下标之间的关系</h3>

<p>JavaScript 数组的 {{jsxref("Array.length", "length")}} 属性和其数字下标之间有着紧密的联系。数组内置的几个方法(例如 {{jsxref("Array.join", "join")}}{{jsxref("Array.slice", "slice")}}{{jsxref("Array.indexOf", "indexOf")}} 等)都会考虑 {{jsxref("Array.length", "length")}} 的值。另外还有一些方法(例如 {{jsxref("Array.push", "push")}}{{jsxref("Array.splice", "splice")}} 等)还会改变 {{jsxref("Array.length", "length")}} 的值。</p>

<pre class="brush: js  language-js">var fruits = [];
fruits.push('banana', 'apple', 'peach');

console.log(fruits.length); // 3
</pre>

<p>使用一个合法的下标为数组元素赋值,并且该下标超出了当前数组的大小的时候,解释器会同时修改 {{jsxref("Array.length", "length")}} 的值:</p>

<pre class="brush: js  language-js">fruits[5] = 'mango';
console.log(fruits[5]); // 'mango'
console.log(Object.keys(fruits));  // ['0', '1', '2', '5']
console.log(fruits.length); // 6
</pre>

<p>也可以显式地给 {{jsxref("Array.length", "length")}} 赋一个更大的值:</p>

<pre class="brush: js  language-js">fruits.length = 10;
console.log(Object.keys(fruits)); // ['0', '1', '2', '5']
console.log(fruits.length); // 10
</pre>
<p>而为 {{jsxref("Array.length", "length")}} 赋一个更小的值则会删掉一部分元素:</p>

<pre class="brush: js  language-js">fruits.length = 2;
console.log(Object.keys(fruits)); // ['0', '1']
console.log(fruits.length); // 2</pre>

<p>这一节的内容在 {{jsxref("Array.length")}} 中有更详细的介绍。</p>
<h3 id="正则匹配结果所返回的数组">正则匹配结果所返回的数组</h3>

<p>使用正则表达式匹配字符串可以得到一个数组。这个数组中包含本次匹配的相关信息和匹配结果。{{jsxref("RegExp.exec")}}{{jsxref("String.match")}}{{jsxref("String.replace")}} 都会返回这样的数组。看下面的例子和例子下面的表格:</p>

<pre class="brush: js">// 匹配1个 d 后面紧跟着至少1个 b,再后面又跟着1个 d 的子串,
// 并且需要记住子串中匹配到的 b 和最后的 d (通过正则表达式中的分组),
// 同时在匹配时忽略大小写

myRe = /d(b+)(d)/i;
myArray = myRe.exec("cdbBdbsbz");
</pre>

<p>该正则匹配返回的数组包含以下属性和元素:</p>

<table class="fullwidth-table">
 <tbody>
  <tr>
   <td class="header">属性/元素</td>
   <td class="header">说明</td>
   <td class="header">示例</td>
  </tr>
  <tr>
   <td><code>input</code></td>
   <td>只读属性,原始字符串</td>
   <td>cdbBdbsbz</td>
  </tr>
  <tr>
   <td><code>index</code></td>
   <td>只读属性,匹配到的子串在原始字符串中的索引</td>
   <td>1</td>
  </tr>
  <tr>
   <td><code>[0]</code></td>
   <td>只读元素,本次匹配到的子串</td>
   <td>dbBd</td>
  </tr>
  <tr>
   <td><code>[1], ...[n]</code></td>
   <td>只读元素,正则表达式中所指定的分组所匹配到的子串,其数量由正则中的分组数量决定,无最大上限</td>
   <td>[1]: bB<br>
    [2]: d</td>
  </tr>
 </tbody>
</table>

<h2 id="属性">属性</h2>

<div><code>Array.length</code></div>

<dl>
 <dd><code>Array</code> 构造函数的 length 属性,其值为1(注意该属性为静态属性,不是数组实例的 length 属性)。</dd>
 <dt>{{jsxref("Array.@@species", "get Array[@@species]")}}</dt>
 <dd>返回 <code>Array</code> 构造函数。</dd>
 <dt>{{jsxref("Array.prototype")}}</dt>
 <dd>通过数组的原型对象可以为所有数组对象添加属性。</dd>
</dl>

<h2 id="方法">方法</h2>

<dl>
 <dt>{{jsxref("Array.from()")}}</dt>
 <dd>从类数组对象或者可迭代对象中创建一个新的数组实例。</dd>
 <dt>{{jsxref("Array.isArray()")}}</dt>
 <dd>用来判断某个变量是否是一个数组对象。</dd>
 <dt>{{jsxref("Array.of()")}}</dt>
 <dd>根据一组参数来创建新的数组实例,支持任意的参数数量和类型。</dd>
</dl>

<h2 id="数组实例"><font face="Consolas, Liberation Mono, Courier, monospace">数组实例</font></h2>

<p>所有数组实例都会从 {{jsxref("Array.prototype")}} 继承属性和方法。修改 <code>Array</code> 的原型会影响到所有的数组实例。</p>

<h3 id="属性_2">属性</h3>

<div>{{page('/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Properties')}}</div>

<h3 id="方法_2">方法</h3>

<h4 id="修改器方法">修改器方法</h4>

<p>{{page('zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Mutator_methods')}}</p>

<h4 id="访问方法">访问方法</h4>

<p>{{page('zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Accessor_methods')}}</p>

<h4 id="迭代方法">迭代方法</h4>

<p>{{page('zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Iteration_methods')}}</p>

<h2 id="数组泛型方法">数组泛型方法</h2>

<div class="warning">
<p><strong>泛型方法是非标准,并且已弃用,有可能不久就会移除。</strong> 需注意的是此方法同时有跨浏览器问题. 但是 <a href="https://github.com/plusdude/array-generics">Github上有可用的shim</a></p>
</div>

<p>有时我们会希望在字符串或其他类数组对象上使用数组所提供的方法(如函数的 {{jsxref("Functions/arguments", "arguments", "", 1)}})。此时你可以把一个字符串作为一个字符数组来看待(也就是说,把非数组以某种方式看成是一个数组)。比如,可以用下面的方法来检查变量 <code>str</code> 中的字符是否都是字母:</p>

<pre class="brush: js">function isLetter(character) {
  return character &gt;= 'a' &amp;&amp; character &lt;= 'z';
}

if (Array.prototype.every.call(str, isLetter)) {
  console.log("The string '" + str + "' contains only letters!");
}</pre>

<p>这种方法能够行得通,但不够简洁,JavaScript 1.6 中引入了一个泛型化的简写形式:</p>

<pre class="brush: js">if (Array.every(str, isLetter)) {
  console.log("The string '" + str + "' contains only letters!");
}</pre>

<p>{{jsxref("Global_Objects/String", "String")}} 对象也包含一些泛型方法,见: {{jsxref("Global_Objects/String", "Generics", "#String_generic_methods", 1)}}</p>

<p>注意,这些并不属于 ECMAScript 标准,也不能在非 Gecko 浏览器中使用。你可以用标准方法 {{jsxref("Array.from()")}} 来替代上面的写法, <code>from</code> 方法可以将一个对象转换为真正的数组(虽然老的浏览器可能不支持):</p>

<pre class="brush: js"><code>if (Array.from(str).every(isLetter)) {
  console.log("The string '" + str + "' contains only letters!");
}</code></pre>

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

<h3 id="创建数组">创建数组</h3>

<p>下面这个例子创建了一个长度为 0 的数组 <code>msgArray</code>,然后给 <code>msgArray[0]</code> 和 <code>msgArray[99]</code> 赋值,从而导致数组长度变为了 100。</p>

<pre class="brush: js">var msgArray = [];
msgArray[0] = 'Hello';
msgArray[99] = 'world';

if (msgArray.length === 100) {
  console.log('The length is 100.');
}</pre>

<h3 id="创建二维数组">创建二维数组</h3>

<p>下面的例子创建了一个代表国际象棋棋盘的二维数组,然后将 (6, 4) 上的 Pawn (卒)拷贝到 (4, 4) 位置,而原本 (6, 4) 位置则被设置为空格。</p>

<pre class="brush: js">var board = [
  ['R','N','B','Q','K','B','N','R'],
  ['P','P','P','P','P','P','P','P'],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  [' ',' ',' ',' ',' ',' ',' ',' '],
  ['p','p','p','p','p','p','p','p'],
  ['r','n','b','q','k','b','n','r'] ];

console.log(board.join('\n') + '\n\n');

// Move King's Pawn forward 2
board[4][4] = board[6][4];
board[6][4] = ' ';
console.log(board.join('\n'));
</pre>

<p>下面是输出:</p>

<pre class="brush: js">R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
 , , , , , , ,
p,p,p,p,p,p,p,p
r,n,b,q,k,b,n,r

R,N,B,Q,K,B,N,R
P,P,P,P,P,P,P,P
 , , , , , , ,
 , , , , , , ,
 , , , ,p, , ,
 , , , , , , ,
p,p,p,p, ,p,p,p
r,n,b,q,k,b,n,r
</pre>

<h3 id="用数组将一组值以表格形式显示">用数组将一组值以表格形式显示</h3>

<pre class="brush: js"><code>values = [];
for (var x = 0; x &lt; 10; x++){
 values.push([
  2 ** x,
  2 * x ** 2
 ])
};
console.table(values)</code></pre>

<p>结果为:</p>

<pre><code>0	1	0
1	2	2
2	4	8
3	8	18
4	16	32
5	32	50
6	64	72
7	128	98
8	256	128
9	512	162</code></pre>

<p>(第一列为索引)</p>

<h2 id="规范">规范</h2>

<table class=" standard-table">
 <tbody>
  <tr>
   <th scope="col">规范</th>
   <th scope="col">状态</th>
   <th scope="col">说明</th>
  </tr>
  <tr>
   <td>{{SpecName('ES1')}}</td>
   <td>{{Spec2('ES1')}}</td>
   <td>初始定义。</td>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.4', 'Array')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td>新增方法: {{jsxref("Array.isArray")}}, {{jsxref("Array.prototype.indexOf", "indexOf")}}, {{jsxref("Array.prototype.lastIndexOf", "lastIndexOf")}}, {{jsxref("Array.prototype.every", "every")}}, {{jsxref("Array.prototype.some", "some")}}, {{jsxref("Array.prototype.forEach", "forEach")}}, {{jsxref("Array.prototype.map", "map")}}, {{jsxref("Array.prototype.filter", "filter")}}, {{jsxref("Array.prototype.reduce", "reduce")}}, {{jsxref("Array.prototype.reduceRight", "reduceRight")}}</td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-array-objects', 'Array')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td>
    <p>新增方法:{{jsxref("Array.from")}}, {{jsxref("Array.of")}}, {{jsxref("Array.prototype.find", "find")}}, {{jsxref("Array.prototype.findIndex", "findIndex")}}, {{jsxref("Array.prototype.fill", "fill")}}, {{jsxref("Array.prototype.copyWithin", "copyWithin")}}</p>
   </td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-array-objects', 'Array')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>
    <p>新增方法:{{jsxref("Array.prototype.includes()")}}</p>
   </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 href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div>

<div>{{Compat("javascript.builtins.Array")}}</div>

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

<ul>
 <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects#Indexing_object_properties">JavaScript Guide: “Indexing object properties”</a></li>
 <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Predefined_Core_Objects#Array_Object">JavaScript Guide: “Predefined Core Objects: <code>Array</code> Object”</a></li>
 <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Array_comprehensions">Array comprehensions</a></li>
 <li><a href="https://github.com/plusdude/array-generics">Polyfill for JavaScript 1.8.5 Array Generics and ECMAScript 5 Array Extras</a></li>
 <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays">Typed Arrays</a></li>
</ul>