最近試用了 prototype.js ,實在是非常好用。複雜的 AJAX 以及事件處理, prototype.js 都包裝好了。
prototype.js 也為 JavaScript 原來的 String 、 Array 物件擴充了一些功能,使得我們在使用這些物件時能更方便。
不過我卻遇到了一個小麻煩,因為在我負責的專案裡,有用到了一個 HtmlArea 的線上 HTML 編輯器。原來嵌有 HtmlArea 的頁面,運作上非常順利;直到加入 prototype.js 後,就會出現 JS Error 了。
以下是我模擬出問題的程式:
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
| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=big5" />
<title>Test Array in prototype.js</title>
<script type="text/javascript" src="j/prototype.js"></script>
</head>
<body>
<script type="text/javascript">
<!--
var toolbar = [
['linebreak'],
['aaa', 'bbbb', 'cccc', 'dddd'],
['111', '2222', '3333', '4444'],
['linebreak'],
['hhh', 'ggg'],
];
for (var i in toolbar) {
if (toolbar[i].length == 1 &&
toolbar[i][0].toLowerCase() == "linebreak") {
document.write('check: ' + toolbar[i][0] + '<br />');
}
}
//-->
</script>
</body>
</html>
|
如果你在瀏覽器 (IE 或 Firefox 皆可) 上執行上面的程式時,就會出現錯誤訊息:
1
2
| 錯誤: 'toolbar[...].0' 是 null 或不是一個物件 (IE)
toolbar[i][0] has no properties (Firefox)
|
原因出在這裡:
因為 prototype.js 擴充了陣列物件,因此如果使用 for…in 敘述的話,會使得 i 除了抓到我們定義的陣列索引值之外,還會抓到 prototype.js 所擴充的函式指標。
不信的話,我們可以試著先將 i 寫出來:
1
2
3
| for (var i in toolbar) {
document.write(i + '<br />');
}
|
結果為:
1
2
3
4
5
6
7
8
9
10
11
| 0
1
2
3
4
each
all
...[略]...
compact
flatten
without
|
在使用 prototype.js 後,當我們存取到 toolbar 這個陣列的第一個函式指標時, toolbar[i][0] 是不存在的,所以就會發生錯誤;也因此我們就不能使用 for…in 來列舉陣列了。
那麼要怎麼在使用 prototype.js 後列舉陣列值呢?第一種是傳統的方法:
1
2
3
| for (var i = 0; i < toolbar.length; i ++) {
document.write(toolbar[i] + '<br />');
}
|
這時候 i 是索引值,因此要取得元素值就要用 toolbar[i] 。
第二種是用 prototype.js 擴充的 each 方法:
1
2
3
| toolbar.each(function(e) {
document.write(e + '<br />'); // 這邊的 e 相當於上面的 toolbar[i]
});
|
使用 each 方法時,可以傳給它一個函式實字 (function literal) ,這個函式的唯一參數就是陣列的元素值。 each 方法在會自動跑遍陣列裡的元素,然後把元素值傳給剛剛丟給它的函式實字去執行。
參考文章: Why I Don't Use The prototype.js JavaScript Library