「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) { ... }
を囲む [] は要らなくなります。
Posted by Hiroyuki KUROSAKI at 2005年10月13日 09:33<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>
今回は、前回の記事「JavaScriptの演算子」の続きです。
今回はプログラム初心者の方には理解しにくい部分が多く、きっと一度読んだだ...
サイン・インを確認しました、 さん。コメントしてください。 (サイン・アウト)
(いままで、ここでコメントしたとがないときは、コメントを表示する前にこのウェブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)