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
446
447
448
449
450
451
452
453
|
---
title: 陣列的運用
slug: conflicting/Web/JavaScript/Guide
translation_of: Web/JavaScript/Guide
translation_of_original: Web/JavaScript/Guide/Obsolete_Pages/Working_with_Arrays
original_slug: Web/JavaScript/Obsolete_Pages/Obsolete_Pages/Obsolete_Pages/陣列的運用
---
<p>陣列是值的有序序列。有別於其他的語言,JavaScript 並沒有明確的陣列資料類型。取而代之,提供了 <code>Array</code> 物件,可以直接實體化或使用陣列的字面表達記法。</p>
<p>Array 物件有以各種方式操作陣列的方法,如合併、反轉、排序。他有一個用來指定陣列長度的屬性。JavaScript 也提供有用的陣列的字面表達語法,用來建立這些物件。</p>
<h3 id="陣列的建立" name="陣列的建立">陣列的建立</h3>
<p>陣列可以使用字面表達語法(通常是首選)或使用 Array 的建構子(也可以稱作函數,兩者行為完全相同)來建立︰</p>
<pre class="eval">var colors = ["Red", "Green", "Blue"];
var colors = new Array("Red", "Green", "Blue");
var colors = Array("Red", "Green", "Blue");
</pre>
<p>陣列具有 length 屬性,提供來存取陣列的長度。如果你使用上述其中一個例子來初始化陣列,陣列的長度將會是 3︰</p>
<pre class="eval">print(colors.length); // 3
</pre>
<p>在建立陣列的時候,如果你知道你的陣列的預期長度,你可以給 Array 的建構子傳入長度︰</p>
<pre class="eval">var fiveItems = new Array(5);
</pre>
<p>明確定義長度並不會影響陣列的實際容量;這樣只會影響新陣列的 <code>length</code> 屬性。(陣列本身並沒有小於指定值的索引的屬性。)構建子的變體極少使用到。</p>
<p>JavaScript 1.7 引入陣列的簡約式作為建立新陣列的捷徑;<a class="internal" href="/zh_tw/Core_JavaScript_1.5_%E6%95%99%E5%AD%B8/%E9%99%A3%E5%88%97%E7%9A%84%E9%81%8B%E7%94%A8#%E9%99%A3%E5%88%97%E7%9A%84%E7%B0%A1%E7%B4%84%E5%BC%8F" title="zh tw/Core JavaScript 1.5 教學/陣列的運用#陣列的簡約式">下面</a> 會討論。</p>
<h3 id="陣列元素的運用" name="陣列元素的運用">陣列元素的運用</h3>
<p>你可以透過把值代入給陣列元素的方式儲存陣列。下面是我們的範例 <code>colors</code> 陣列更為完整的實例︰</p>
<pre class="eval">var colors = []; // 空陣列
print(colors.length); // 0
colors[0] = 'Red';
colors[1] = 'Green';
colors[2] = 'Blue';
print(colors.length); // 3
</pre>
<p>附加元素至陣列的末端的常見習慣是使用 <code>array.length</code> 作為索引︰</p>
<pre class="eval">colors[colors.length] = 'Orange';
</pre>
<p>可以使用 <code>array.push()</code> 方法達到同樣效果︰</p>
<pre class="eval">colors.push('Purple');
</pre>
<p>陣列的元素使用元素的索引來存取。陣列是以 0 開始索引,因此陣列中的第一個元素是 0︰</p>
<pre class="eval">var red = colors[0];
</pre>
<p>可以使用各式各樣的陣列方法來存取陣列的元素。例如,<code>pop()</code> 方法移除並返回陣列的最後一個元素︰</p>
<pre class="eval">var lastElement = colors.pop(); /* colors 的最後一個元素也被移除 */
</pre>
<h3 id="理解_length" name="理解_length">理解 length</h3>
<p>以實作的層級來說,JavaScript 的陣列實際上把元素存放成標準的物件屬性,並使用陣列的索引作為屬性的名稱。<code>length</code> 屬性很特別;他永遠會返回比保存在陣列中的最高索引值再高一的值︰</p>
<pre class="eval">var cats = [];
cats[30] = ['Dusty'];
print(cats.length); // 31
</pre>
<p>你也可以把值代入給 <code>length</code> 屬性。寫下小於陣列中已存放的項目的數目,就會截掉其餘的項目;寫下 0 就完全清空陣列︰</p>
<pre class="eval">var cats = ['Dusty', 'Misty', 'Twiggy'];
print(cats.length); // 3
cats.length = 2;
print(cats); // 輸出 "Dusty,Misty" - Twiggy 被移除了
cats.length = 0;
print(cats); // 什麼也沒輸出;cats 陣列是空的
</pre>
<h3 id="迭代整個陣列" name="迭代整個陣列">迭代整個陣列</h3>
<p>常見的操作就是迭代所有陣列的值,並以同樣方式處理每一個值。做到這一點的最簡單的方式如下︰</p>
<pre class="eval">var colors = ['red', 'green', 'blue'];
for (var i = 0; i < colors.length; i++) {
alert(colors[i]);
}
</pre>
<p>如果你知道陣列中沒有一個元素會在布林的求值結果中為 false - 如果你的陣列只以 DOM 的結點組成,例如,你可以使用更有效率的習慣︰</p>
<pre class="eval">var divs = document.getElementsByTagName('div');
for (var i = 0, div; div = divs[i]; i++) {
/* 以同樣方式處理 div */
}
</pre>
<p>這樣可以避免檢查陣列長度的開支,並且確保 div 變數被重新指定到每一次循環的使用中項目,以方便加入。</p>
<p> <a class="internal" href="/zh_tw/Core_JavaScript_1.5_%E5%8F%83%E8%80%83/%E5%85%A8%E5%9F%9F%E7%89%A9%E4%BB%B6/Array/forEach" title="zh tw/Core JavaScript 1.5 參考/全域物件/Array/forEach"><code>forEach</code></a> 方法是在 JavaScript 1.6 引入的,提供了另一種迭代陣列的方式︰</p>
<pre class="eval">var colors = ['red', 'green', 'blue'];
colors.forEach(function(color) {
alert(color);
});
</pre>
<p>傳給 <code>forEach</code> 的函數會在陣列中的每一個項目中執行一次,並把陣列的項目傳給函數作為參數。</p>
<h3 id="Array_的方法" name="Array_的方法">Array 的方法</h3>
<p><code>Array</code> 物件有以下的方法︰</p>
<ul>
<li><code>concat</code> 合併兩個陣列,並把新的陣列返回。</li>
</ul>
<pre class="eval">var a1 = [1, 2, 3];
var a2 = a1.concat(['a', 'b', 'c']);
print(a2); // 1,2,3,a,b,c
</pre>
<ul>
<li><code>join(deliminator = ",")</code> 把所有的陣列元素合併成字串。</li>
</ul>
<pre class="eval">var a = ['Wind', 'Rain', 'Fire'];
print(a.join(' - ')); // "Wind - Rain - Fire"
</pre>
<ul>
<li><code>pop</code> 移除掉陣列的最後一個元素,並把這個元素返回。</li>
</ul>
<pre class="eval">var a = [1, 2, 3];
var last = a.pop();
print(a); // 1,2
print(last); // 3
</pre>
<ul>
<li><code>push</code> 在陣列的末端加入一個以上的元素,並返回新的陣列長度。</li>
</ul>
<pre class="eval">var a = [1, 2];
a.push(3);
print(a); // 1,2,3
</pre>
<ul>
<li><code>reverse</code> 反轉陣列元素的順序至適當的位置。</li>
</ul>
<pre class="eval">var a = [1, 2, 3, 4];
a.reverse();
print(a); // 4,3,2,1
</pre>
<ul>
<li><code>shift</code> 移除並返回陣列的第一個元素。</li>
</ul>
<pre class="eval">var a = [1, 2, 3];
var first = a.shift();
print(a); // 2,3
print(first); // 警報 1
</pre>
<ul>
<li><code>unshift</code> 在陣列的開頭處加入一個以上的元素,並返回新的陣列長度。</li>
</ul>
<pre class="eval">var a1 = [1, 2, 3];
a1.unshift(4);
print(a1); // 4,1,2,3
</pre>
<ul>
<li><code>slice (start_index, upto_index)</code> 返回陣列的片斷。</li>
</ul>
<pre class="eval">var a1 = ['a', 'b', 'c', 'd', 'e'];
var a2 = a1.slice(1, 4);
print(a2); // 警報 b,c,d
</pre>
<ul>
<li><code>splice(index, count_to_remove, addelement1, addelement2, ...)</code> 加入 和/或 移除陣列的元素,在適當的位置修改。</li>
</ul>
<pre class="eval">var a = ['a', 'b', 'c', 'd', 'e'];
var removed = a.splice(1, 3, 'f', 'g', 'h', 'i');
print(removed); // b,c,d
print(a); // a,f,g,h,i,e
</pre>
<ul>
<li><code>sort</code> 在適當的位置排序陣列的元素。</li>
</ul>
<pre class="eval">var a = ['Wind', 'Rain', 'Fire'];
a.sort();
print(a); // Fire,Rain,Wind
</pre>
<p><code>sort</code> 也可以接受 Callback 函數來決定如何排序陣列的內容。這個函數會對兩個值做比較,並返回下列三個值其中之一︰</p>
<ul>
<li>如果 a 在排序系統中小於 b,返回 -1(或任意的負數)</li>
<li>如果 a 在排序系統中大於 b,返回 1(或任意的正數)</li>
<li>如果 a 和 b 被認為是相等的,返回 0。</li>
</ul>
<p>例如,下面的例子會以字串的最後一個字母來排序︰</p>
<pre class="eval">var a = ['Wind', 'Rain', 'Fire'];
function sortFn(a, b) {
var lastA = a[a.length - 1];
var lastB = b[b.length - 1];
if (lastA < lastB) return -1;
if (lastA > lastB) return 1;
if (lastA == lastB) return 0;
}
a.sort(sortFn);
print(a); // Wind,Fire,Rain
</pre>
<h4 id="於_JavaScript_1.6_引入" name="於_JavaScript_1.6_引入">於 JavaScript 1.6 引入</h4>
<ul>
<li><code>indexOf(searchElement[, fromIndex)</code> 在陣列中搜尋 <code>searchElement</code> 並返回第一個符合項的索引。</li>
</ul>
<p> </p>
<pre class="eval"> var a = ['a', 'b', 'a', 'b', 'a'];
alert(a.indexOf('b')); // 警報 1
// 現在再試一次,從最後的符合項之後的索引開始
alert(a.indexOf('b', 2)); // 警報 3
alert(a.indexOf('z')); // 警報 -1,因為找不到 'z'
</pre>
<p> </p>
<ul>
<li><code>lastIndexOf(searchElement[, fromIndex)</code> 類似 <code>indexOf</code>,但是最後面開始往回搜尋。</li>
</ul>
<p> </p>
<pre class="eval"> var a = ['a', 'b', 'c', 'd', 'a', 'b'];
alert(a.lastIndexOf('b')); // 警報 5
// 現在再試一次,從最後的符合項之前的索引開始
alert(a.lastIndexOf('b', 4)); // 警報 1
alert(a.lastIndexOf('z')); // 警報 -1
</pre>
<p> </p>
<ul>
<li><code>forEach(callback{{ mediawiki.external(', thisObject') }})</code> 在每一個項目上執行 <code>callback</code>。</li>
</ul>
<p> </p>
<pre class="eval"> var a = ['a', 'b', 'c'];
a.forEach(alert); // 依序警報每一個項目
</pre>
<p> </p>
<ul>
<li><code>map(callback{{ mediawiki.external(', thisObject') }})</code> 返回在每一個陣列的項目上執行 <code>callback</code> 所返回的值的新陣列。</li>
</ul>
<p> </p>
<pre class="eval"> var a1 = ['a', 'b', 'c'];
var a2 = a1.map(function(item) { return item.toUpperCase(); });
alert(a2); // 警報 A,B,C
</pre>
<p> </p>
<ul>
<li><code>filter(callback{{ mediawiki.external(', thisObject') }})</code> 返回內含在 Callback 中返回為 true 的項目的新陣列。</li>
</ul>
<p> </p>
<pre class="eval"> var a1 = ['a', 10, 'b', 20, 'c', 30];
var a2 = a1.filter(function(item) { return typeof item == 'number'; });
alert(a2); // 警報 10,20,30
</pre>
<p> </p>
<ul>
<li><code>every(callback{{ mediawiki.external(', thisObject') }})</code> 返回 true,如果 <code>callback</code> 在陣列中的每一項上都返回 true。</li>
</ul>
<p> </p>
<pre class="eval"> function isNumber(value) { return typeof value == 'number'; }
var a1 = [1, 2, 3];
alert(a1.every(isNumber)); // 警報 true
var a2 = [1, '2', 3];
alert(a2.every(isNumber)); // 警報 false
</pre>
<p> </p>
<ul>
<li><code>some(callback{{ mediawiki.external(', thisObject') }})</code> 返回 true,如果 <code>callback</code> 在陣列中至少有一個項目返回為 true。</li>
</ul>
<p> </p>
<pre class="eval"> function isNumber(value) { return typeof value == 'number'; }
var a1 = [1, 2, 3];
alert(a1.some(isNumber)); // 警報 true
var a2 = [1, '2', 3];
alert(a2.some(isNumber)); // 警報 true
var a3 = ['1', '2', '3'];
alert(a3.some(isNumber)); // 警報 false
</pre>
<p> </p>
<p>上面接受 Callback 的方法又稱為<em>迭代方法</em>,因為他們會以同樣的方式迭代整個陣列。其中第二個選用性的參數稱為 <code>thisObject</code>。如果有提供的話,<code>thisObject</code> 會變成 Callback 函數的本體內部的 <code>this</code> 關鍵字的值。</p>
<p>實際上 Callback 函數會以三個參數來呼叫。第一個是使用中項目的值,第二個是他的陣列索引,第三個是陣列本身的參考。JavaScript 函數會忽略任何沒有在參數列表中命名的參數,因此提供只接受單一參數的 Callback 函數也很安全,如 <code>alert</code>。</p>
<h4 id="於_JavaScript_1.8_引入" name="於_JavaScript_1.8_引入">於 JavaScript 1.8 引入</h4>
<ul>
<li><code>reduce(callback[, initialValue)</code> 使用 <code>callback(firstValue, secondValue)</code> 把項目的列表合併成單一的值。</li>
</ul>
<p> </p>
<pre class="eval"> var a = [10, 20, 30];
var total = a.reduce(function(first, second) { return first + second; }, 0);
alert(total) // 警報 60
</pre>
<p> </p>
<ul>
<li><code>reduceRight(callback[, initialValue)</code> 類似 <code>reduce</code>,但是從最後一個元素開始。</li>
</ul>
<p><code>reduce</code> 和 <code>reduceRight</code> 明顯是迭代陣列的方法中最少的。為了把序列降至單一的值,應該把他們用於遞歸合併兩個值的演算法。</p>
<h3 id="近似陣列的物件的運用" name="近似陣列的物件的運用">近似陣列的物件的運用</h3>
<p> 某些 JavaScript 物件,如 <code>document.getElementsByTagName</code> 返回的 NodeList,或者在函數本體內部可以利用的 <code>arguments</code> 物件,表面上看來外觀和行為和陣列很類似,但並未共用所有的方法。例如,<code>arguments</code> 物件提供 <code>length</code> 屬性,但並未實作 <code>forEach</code> 方法。</p>
<p>在 JavaScript 1.6 中引入的通用陣列,為其他類似陣列的物件提供執行 <code>Array</code> 方法的途徑。每一個標準的陣列方法在 <code>Array</code> 物件本身都有相對應的方法;例如︰</p>
<pre class="eval"> function alertArguments() {
Array.forEach(arguments, function(item) {
alert(item);
});
}
</pre>
<p>這些通用方法可以在舊版本的 JavaScript 中,使用由 JavaScript 函數物件所提供的 call 方法,以更冗長的形式模擬。</p>
<pre class="eval"> Array.prototype.forEach.call(arguments, function(item) {
alert(item);
});
</pre>
<p>陣列的通用方法也可以使用在字串上,因為字串提供的對字元循序存取的方式,和陣列的很類似︰</p>
<pre class="eval"> Array.forEach("a string", function(char) {
alert(char);
});
</pre>
<h3 id="二維陣列" name="二維陣列">二維陣列</h3>
<p>下面的代碼建立二維陣列。</p>
<pre>var a = [];
for (i = 0; i < 4; i++) {
a[i] = [];
for (j = 0; j < 4; j++) {
a[i][j] = "[" + i + ", " + j + "]";
}
}
</pre>
<p>本例以如下的行來建立陣列︰</p>
<pre>行 0: [0,0][0,1][0,2][0,3]
行 1: [1,0][1,1][1,2][1,3]
行 2: [2,0][2,1][2,2][2,3]
行 3: [3,0][3,1][3,2][3,3]
</pre>
<h3 id="陣列的簡約式" name="陣列的簡約式">陣列的簡約式</h3>
<p>在 JavaScript 1.7 中引入的陣列簡約式(array comprehension),對於以其他內容為基礎來建構新陣列提供了很有用的捷徑。簡約式通常可以用在 <code>map()</code> 和 <code>filter()</code> 呼叫的地方,或是結合這兩者的方式。</p>
<p>下面的簡約式接收數字的陣列,並建立每一個數字的雙倍的新陣列。</p>
<pre>var numbers = [1, 2, 3, 4];
var doubled = [i * 2 for each (i in numbers)];
alert(doubled); // 警報 2,4,6,8
</pre>
<p>這等同於下面的 <code>map()</code> 操作︰</p>
<pre>var doubled = numbers.map(function(i) { return i * 2; });
</pre>
<p>簡約式也可以用於選取符合特定表達式的項目。這是只選取偶數的簡約式︰</p>
<pre>var numbers = [1, 2, 3, 21, 22, 30];
var evens = [i for each (i in numbers) if (i % 2 == 0)];
alert(evens); // 警報 2,22,30
</pre>
<p><code>filter()</code> 也可以用於同樣的用途︰</p>
<pre>var evens = numbers.filter(function(i) { return i % 2 == 0; });
</pre>
<p><code>map()</code> 和 <code>filter()</code> 這類型的操作可以合併至單一的陣列簡約式。這是只篩出偶數的簡約式,然後建立內含雙倍數值的新陣列。</p>
<pre>var numbers = [1, 2, 3, 21, 22, 30];
var doubledEvens = [i * 2 for each (i in numbers) if (i % 2 == 0)];
alert(doubledEvens); // 警報 4,44,60
</pre>
<p>陣列簡約式的方括號導入了默許的作用域區塊。新的變數(如範例中的 i)會被視為已經使用 <code>let</code> 宣告過了。其意義是不能在簡約式的外部使用這些變數。</p>
<p>輸入到陣列的簡約式本身並不需要是陣列;也可以使用 <a class="internal" href="/zh_tw/JavaScript_1.7_%E6%96%B0%E9%AE%AE%E4%BA%8B#%E8%BF%AD%E4%BB%A3%E5%99%A8%E5%92%8C%E7%94%A2%E7%94%9F%E5%99%A8" title="zh tw/JavaScript 1.7 新鮮事#迭代器和產生器">迭代器和產生器</a>。</p>
<p>{{ PreviousNext("Core_JavaScript_1.5_教學:繼承", "Core_JavaScript_1.5_教學:迭代器和產生器") }}</p>
<p>{{ languages( { "en": "en/Core_JavaScript_1.5_Guide/Working_with_Arrays" } ) }}</p>
|