4-1 }C簡

陣列 (Arrays) 是 JavaScript 提供的內建物件 (Built-in Object) 之一,其功能強大,可大幅度簡化你的程式碼。簡單的說,陣列是一個變數,但它可以儲存許多個值(可以是字串、數值,或是另一個物件),我們可以使用索引 (Index) 或下標(Subscript)來存取每一個元素的值,索引從 0 開始,例如陣列 A 的第一個元素為 A[0],第五個元素為 A[4],依此類推,這是最常用的陣列元素存取方式。(這部分和C語言是一致的。)

要使用陣列變數時,需先宣告,但可以不用設定陣列的元素個數,然後再把元素一個一個加進去,例如:

Example(array01.htm):

上述範例的原始檔如下:

原始檔(array01.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>陣列的建構</h2>
<hr>

<script>
myArray = new Array();			// 產生一個空的陣列
myArray[0] = "This is a test";		// 加入第 1 個元素 
myArray[1] = 3.1415926;			// 加入第 2 個元素 
myArray[2] = "The last element";	// 加入第 3 個元素 
document.writeln("myArray[0] = " + myArray[0] + "<br>");
document.writeln("myArray[1] = " + myArray[1] + "<br>");
document.writeln("myArray[2] = " + myArray[2] + "<br>");
</script>

<hr>
</body>
</html>

亦可將元素值一次指定完成:

myArray = new Array("This is a test", 3.1415926, "The last element");

更簡單的方法,則是將陣列的各個元素放在中括弧內:

myArray = ["This is a test", 3.1415926, "The last element"];

若要一次印出陣列的所有內容來進行檢視,可用下列函式

原始檔(listArray.js):(灰色區域按兩下即可拷貝)
// 列印陣列
function listArray(array, arrayName) {
	for (var i=0; i<array.length; i++) {
		document.write(arrayName+"["+i+"] = ");
		document.write("<font color=green>"+array[i]+"</font><br>");
	}
}

其中 array 代表傳入函數的陣列,arrayName 則是此陣列的名稱,而 array.length 則是陣列 array 的元素個數。

Hint
在上述函示定義中,是否可以不傳入 arrayName,而直接由 array 找到陣列的名稱?我還沒有找到解法,請讀者或同學們幫忙找找看。

例如,將 myArray 以上述的函式印出,可得

Example(array02.htm):

上述範例的原始檔如下:

原始檔(array02.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>陣列的列印</h2>
<hr>

<script src=listArray.js></script>
<script>
myArray = ["This is a test", 3.1415926, "The last element"]; 
listArray(myArray, "myArray");
document.write("myArray = " + myArray);
</script>
<hr>
</body>
</html>

在上述範例中,我們是將 listArray() 函式寫在 listArray.js 檔案之中,並使用下列方式來將此檔案導入上述網頁:

<script src="listArray.js"></script> 這種方式,可以讓我們在不同的網頁導入相同的函式,非常方便,請見後續章節有關於「自訂函數」的說明。

現在我們來看幾個比較完整的網頁,第一個是「每日一句」,可以從 15 個字串中,以亂數的方式挑出一個來顯示,如下:

Example(randomText.htm):

上述範例的原始檔如下:

原始檔(randomText.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>每日一句(利用亂數點選字串陣列的元素)</h2>
<hr>

<script>
text = new Array();
i = 0;
text[i++]="If you don't set aside time for exercise,<br>you'll set aside time for illness.";
text[i++]="不管你們相愛的時間有多長或多短,<p>若你們能始終溫柔地相待,<p>那麼,所有的時刻都將是一種無瑕的美麗,<p>若不得不分離,也要好好的說聲再見,<p>也要在心裡存著感謝,<p>感謝他給了你一份記憶。<br><br>長大了以後,你才會知道,<p>在驀然回首的剎那,<p>沒有怨恨的青春才會了無遺憾,<p>如山岡上那輪靜靜的滿月。<br><br>席慕蓉•無怨的青春";
text[i++]="北方有佳人,遺世而獨立。<p>一顧傾人城,再顧傾人國。";
text[i++] = "∼∼  一次的攜手<p>                                    一生的誓約 ∼∼";
text[i++] ="我曾踏月而去 只因你在山中<p>而在今夜訴說著的熱淚��<br>猶見你微笑的面容<p>叢山暗暗 我華年已逝<p>想林中次次回春 依然<p>會有強健的你 挽我拾級而上<p>而月色如水 芳草淒迷";
text[i++] = "Yesterday is history, Tomorrow is mystery, and Today is a gift. That is why we call it present.";
text[i++] = "愛的反面不是仇恨,而是漠不關心!";
text[i++] = "如何讓你遇見我  在我最美麗的時刻<p>為這  我已在佛前 求了五百年 求祂讓我們結一段塵緣<p>佛於是把我化作一棵樹  長在你必經的路旁 <p>陽光下慎重的開滿了花  朵朵都是我前世的盼望<p>  當你走近  請你細聽 那顫抖的葉是我等待的熱情 <p> 而當你終於無視的走過  在你身後落了一地的...<p>朋友啊  那不是花瓣  是我凋零的心<br><br>席慕蓉•一稞開花的樹";
text[i++] = "Draft beers, not people.";
text[i++] = "Of all the things I lost, I miss my mind most.";
text[i++] = "Choose what you love ...<br>Love what you choose.";
text[i++] = "Rules are made to be broken.";
text[i++] = "Waste bandwidth; not trees!";
text[i++] = "Work like you don't need the money.<br>Love like you've never been hurt.<br>Dance like nobody's watching.";
text[i++] = "曾經滄海難為水,<br>除卻巫山不是雲。<br>取次花叢懶迴顧,<br>半緣修道半緣君。<br><br>元稹•離思";
 
index = Math.floor(Math.random()*text.length);		// 以亂數設定句子的索引值
document.write("<CENTER><table border=2 cellpadding=20 bgcolor=white>");
document.write("<tr><td><b><font size=+2 face=\"標楷體,Helvetical,Arial\" color=#408080>");
document.write(text[index]);
document.write("</font></b></td></tr></table></CENTER>");
</script> 

<hr>
</body>
</html>

在上述範例中,所有的文字都存在一個陣列之中,每此重新載入網頁,就會經由亂數選取一個索引值來挑出句子,所以幾乎每次所選出來的句子都會不一樣。有關於亂數的產生,說明如下:

以同樣的方式,我們也可以在載入網頁時,每此都播放一首亂數選取的 MIDI 音樂檔,例如:

Example(randomMusic.htm):

上述範例的原始檔如下:

原始檔(randomMusic.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>自動點歌機(利用亂數點選背景 MIDI 音樂)</h2>
<hr>

<script>
midiFile = new Array();
songName = new Array();
singerName = new Array();

i = 0;
midiFile[i] = "music/聽海.mid";
songName[i] = "聽海";
singerName[i] = "張惠妹";
i++;
midiFile[i] = "music/膽小鬼.mid";
songName[i] = "膽小鬼";
singerName[i] = "梁詠琪";
i++;
midiFile[i] = "music/如果雲知道.mid";
songName[i] = "如果雲知道";
singerName[i] = "許茹芸";
i++;
midiFile[i] = "music/原來你什麼都不要.mid";
songName[i] = "原來你什麼都不要";
singerName[i] = "張惠妹";
i++;
midiFile[i] = "music/tomorrow.mid";
songName[i] = "明天你是否依然愛我";
singerName[i] = "童安格";

index = Math.floor(Math.random()*midiFile.length);
pickedMidi = midiFile[index];
pickedSongName = songName[index];
pickedSingerName = singerName[index];
document.writeln("<embed src="+pickedMidi+" hidden=false autostart=true loop=false type='audio/midi'>");
</script>

<p align=center>
<script>
document.write("你現在聽到的歌是<font color=green>『"+pickedSingerName+"』</font>的");
document.write("『<font color=red>"+pickedSongName+"</font>』");
</script>

<p>
所有的歌:
<blockquote>
<script>
for (var i = 0; i < midiFile.length; i++) {
	document.write("<font color=green>"+singerName[i]+"</font>:");
	document.write("<font color=red>"+songName[i]+"</font>");
	document.write(" (<a href="+midiFile[i]+">"+midiFile[i]+"</a>)<br>");
}
</script>
</blockquote>

<hr>
</body>
</html>

Hint
在上述範例中,我們使用了三個陣列,分別用來儲存 midi 網址、歌曲名稱、歌手姓名。更好的作法,是用一個陣列來存放這些資料,其中每一個元素代表一首歌曲的資料,包含三個欄位(midi 網址、歌曲名稱、歌手姓名),這樣的資料結構比較模組化。

利用同樣的方式,我們可以隨機產生一張照片,同時也播放隨機背景音樂,如下例:

Example(randomImage.htm):

上述範例的原始檔如下:

原始檔(randomImage.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>自動相簿加點歌機(利用亂數點選影像及背景 MIDI 音樂)</h2>
<hr>

<script>
imageUrl=["image/roger/all.jpg", "image/roger/fall.jpg", "image/roger/grade4.jpg", "image/roger/lake.jpg",
	"image/roger/roger1.gif", "image/roger/roger5.jpg", "image/roger/uniform.jpg", "image/roger/wes.jpg"];
midiUrl=["music/聽海.mid", "music/膽小鬼.mid", "music/如果雲知道.mid", "music/原來你什麼都不想要.mid", "music/tomorrow.mid"];

pickedImage = imageUrl[Math.floor(Math.random()*imageUrl.length)];
pickedMidi = midiUrl[Math.floor(Math.random()*midiUrl.length)];
document.writeln("<embed src="+pickedMidi+" hidden=true autostart=true loop=false>");
</script>

<table align=center border=2>
<tr><td>
<script>document.write("<img src="+pickedImage+">")</script>
</table>

<hr>
</body>
</html>

我們也可以利用兩段隨機產生的文字,來合成另一段文字,那麼文字完全重複的機率就會小很多,例如

Example(punchme.htm):

上述範例的原始檔如下:

原始檔(punchme.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta http-equiv="Refresh" content="3">
</head>

<body>
<h2 align=center>利用亂數合成訊息,並自動更新(3 秒更新一次)</h2>
<hr>

<script>
text1 = new Array();
i = 0;
text1[i++] = "Hey you geek, ";
text1[i++] = "Hey buddy, ";
text1[i++] = "See if you dare to ";
text1[i++] = "To reboot the computer, ";
text1[i++] = "To save the world, ";
text1[i++] = "To get the highest score in the class, ";
text1[i++] = "同學們, ";

text2 = new Array();
i = 0;
text2[i++] = "punch me!";
text2[i++] = "press me!";
text2[i++] = "push me!";
text2[i++] = "hit me with your best shot!";
text2[i++] = "按我一下吧!";
text2[i++] = "揍我一拳吧!";

document.write("<h3 align=center>");
document.write("<font face='Helvetical,Arial' color='#408080'><I>");
document.write(text1[Math.floor(Math.random()*text1.length)]+text2[Math.floor(Math.random()*text2.length)]);
document.write("</I></font>");
document.write("</h3>");
</script>

<center>
<img src="image/roger/roger4.jpg" onMouseDown="this.src='image/roger/newroger.jpg'"
onMouseUp="this.src='image/roger/roger4.jpg'">
</center>

</body>
</html>

在上述範例中,我們在 加了一列 <meta http-equiv="Refresh" content="3">,這一列敘述會讓瀏覽器每 3 秒就重新載入網頁,因此上方的動態訊息就會每 3 秒變動一次。(當然,我們也用了 onMouseOver 和 onMouseUp 的事件,以便即時更換影像,達到趣味性的效果。)

如果我們利用陣列來存放影像物件,就會有快取的效果,換句話說,一旦知道影像物件的網址,JavaScript 會先將影像資料抓回來,等需要呈現影像時,就可以直接從客戶端電腦的記憶體中抓取,省卻了直接從網路抓取的時間,減少了使用者的等待時間,達到了「快取」(Cache)的效果。例如:

Example(rotateImage.htm):

上述範例的原始檔如下:

原始檔(rotateImage.htm):(灰色區域按兩下即可拷貝)
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=big5">
</head>

<body>
<h2 align=center>有快取效果(Cache)的 JavaScript 網頁</h2>
<hr>

<h3 align=center>
點選照片以跳到下一張!
</h3>

<script language="JavaScript">
currentIndex = 0;			// 第一張照片的索引值
imageArray = new Array();		// 產生放影像物件的陣列
photoNum = 42;				// 照片的數目
for (i=0; i<photoNum; i++){
	imageArray[i] = new Image();	// 每個陣列元素都是 Image 物件,所以有快取的效果
	if (i < 10)
		imageArray[i].src = "image/19980425/000"+i+".jpg";
	if ((10 <= i) && (i < 100))
		imageArray[i].src = "image/19980425/00"+i+".jpg";
}

// 傳回下一張照片的網址
function nextImageUrl(){
	currentIndex++;				// 這是全域變數
	currentIndex=currentIndex % photoNum;	// 求餘數
	return(imageArray[currentIndex].src);	// 回傳照片網址
}
</script>

<center>
<img src="image/19980425/0000.jpg" onMouseUp="this.src=nextImageUrl()">
</center>

</body>
</html>

在上述範例中,共用到42張照片,但 JavaScript 會立即將影像資料抓回來,而不會等到使用者點選時,才從網路把影像資料抓回來呈現。(不過這個範例要放在遠端的伺服器才能顯示其效果,若只是在客戶端點選範例,則所有影像資料都在硬碟中,不容易看出快取的效果。)

Hint
如果 imageArray 只是用來存放影像的網址,而不是存放一個影像物件,那就不會有快取的效果。

最後一個範例,是使用網頁來達到類似 Powerpoint 投影片的循序放映效果,請參考下列範例:

Example(slideShow/index.htm):

很顯然的,要儲存這些網頁的資訊來進行循序播放,當然是用陣列最方便。(本範例取材自清華大學計算機與通訊中心、周文正先生的作品,特此致謝。)


JavaScript 程式設計與應用:用於網頁用戶端