MootoolsのNativeクラスは、Javascriptのビルトインクラスをいろいろ拡張してくれるので、なかなか重宝するものらしい。
しかし、Mootoolsが入ってない前提でJavascriptを書いているものと混在させると、いろいろハマる場合がある。
今回はこんな部分が問題となった。
1: var query = urlString.split("?");
2: if( query.length >= 2 ){
3: var prms = query[1].split("&");
4: for (idx in prms) {
5: var prm = prms[idx].split("=");
6: if( prm[0] == 'id' ){ devID = prm[1]; }
7: }
8: }
urlに含まれるGET引数を解析するコードと思われる。
ここで、3行目でsplitでquery[1]分割した結果配列prmsの各要素には「当然」文字列しか入ってないと思ってコードを書いているところがミソ。
実は、prmsの継承元であるArrayは、Mootoolsで拡張されているので、文字列以外に、拡張メソッド(associateとか)が含まれている。
すなわち、query[1]が「id=hoge&foo=piyo」なら、
普通は、
prms[0]: "id=hoge"
prms[1]: "foo=piyo"
しか含まれない。しかし、Mootoolsで拡張されていると、
prms[0]: "id=hoge"
prms[1]: "foo=piyo"
prms[associate]: function() → Array.associate()
prms[contains]: function() → Array.contanis()
となってしまう。
それに気づかずにforループを回すと、5行目が非文字列要素(associateメソッドなど)に対して実行してしまうので、エラーとなってスクリプトは停止してしまう。
(そもそも、2行目のquery.lengthは常に2以上になってしまうので、GET引数がないURLでも3行目以降が実行されるという問題もあるが)
これを回避するには、いろいろ試行錯誤してあげく汚い方法を使った。
次のようなコードを、Mootools読み込み後のどこかで実行してあげる。
<script type="text/javascript">
Array.prototype.split = function(){return Array();};
Function.prototype.split = function(){return Array();};
</script>
つまり、functionオブジェクトに対してもsplit()メソッドを実装しただけ。ホントは、function()にも他のStringオブジェクトのメソッドを全て実装してあげないと、また同じようなことでハマそうな気がするが・・・・。
マナーとしては、splitとかを実行するならString型かどうかしれ部ればいいのに・・・。
ってか、そもそもMootoolsのNativeクラスをいれなければいいのかな。
イヤならいれるな、って思想なのかも。
【Seesaaカスタマイズの最新記事】

