2005年10月13日

[JavaScript] DOMのNodeList (など) にArrayのメソッドを適用する技

Collection & Copy - JavaScriptにおける古典的継承 (ベータ)」を読んでいて、おっ、と目に留まったのは、次のコード。

  r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));

注目したのは、Array.prototype.slice.apply(arguments, [1]) の部分です。

arguments (Argumentsオブジェクト) は配列要素にアクセスする [] 演算子が使えるけれども、Arrayではないので、slice メソッドは持っていません。arguments.slice(1) などとすると、"arguments.slice is not a function" とエラーになります。しかし、どうやら slice メソッドは [] 演算子で実装されているようなので、上のように、Array のメソッドである slice を arguments に適用してやれば、望み通りの結果が得られるわけです。

Arguments.prototype.slice = Array.prototype.slice; とだけやってもよさそうなものですが、これだと "Arguments is not defined" というエラーになります。

そこで思い出したのが、DOMのNodeListの場合。

以前の記事で、 Array.prototype に forEach, map, zip, fold などを追加すると便利だというようなことを書きました。Gecko の JavaScript 1.5 では forEach や map などがサポートされているようですし、prototype.js 1.4.0 でも Ruby にならった関数 (each, map, などなど) が追加されています。

document.getElementsByTagName() が返す NodeList の要素にアクセスするときに、こういうメソッドが使えると便利なんですが、NodeList は Array ではないので、Array.prototype にメソッドを追加しただけでは使えません。また、NodeList.prototype.map = Array.prototype.map; というコードも、FireFox では有効でしたが、IEではエラーになりました。

仕方がないのであきらめて [] 演算子を使ったコードを書いていたんですが、最初のような方法をとれば、ちゃんと動くんですね。以下は試してみたコードです。apply でなく call を使えば function (li) { ... } を囲む [] は要らなくなります。

<html>
<head>
<title>test</title>
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript">
if (!Array.prototype.map) {
    Array.prototype.map = function(f) {
	var ret = new Array();
	for (var i = 0; i < this.length; i++) {
	    ret.push(f(this[i], i, this));
	}
	return ret;
    };
}
window.onload = function () {
    $("message").innerHTML +=
    Array.prototype.map.apply($("myList").getElementsByTagName("li"),
                                          [function(li) {
            return li.firstChild.nodeValue;
        }]).join(", ");
};
</script>
</head>
<body>
<div id="message">
</div>
<ul id="myList">
<li>foo</li>
<li>bar</li>
<li>baz</li>
</ul>
</body>
</html>
Posted by Hiroyuki KUROSAKI at 2005年10月13日 09:33 このエントリーを含むはてなブックマーク
この記事の TrackBack URL:
http://noir.s7.xrea.com/mt/mt-tb.cgi/202
JavaScriptの演算子(2)
Excerpt:

  今回は、前回の記事「JavaScriptの演算子」の続きです。

今回はプログラム初心者の方には理解しにくい部分が多く、きっと一度読んだだ...


Weblog: ネットビジネス用CGI Perl HTML Javascriptの情報サイト
Tracked: 2006年03月22日 08:06
Comments
Post a comment

サイン・インを確認しました、 さん。コメントしてください。 (サイン・アウト)

(いままで、ここでコメントしたとがないときは、コメントを表示する前にこのウェブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)


情報を登録する?