この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
最近Flexの開発が本職になってきたので、ActionScriptを勉強しています。
今回は始めてprototypeを拡張した時に、はまったところを紹介します。
■ setPropertyIsEnumerableについて
prototypeを拡張して関数を追加した時、単に追加しただけだとfor ~ in で要素を列挙する際に、追加した関数も列挙されています。これを防ぐにはsetPropertyIsEnumerableを呼んで、追加した関数を列挙しないようにしなくては行けません。
たとえば、以下のソースは実際のプロジェクトではまった部分ですが、
Array.prototype.find = function(property:String,value:Object):Object{
return this.filter(function(element:*,index:int,arr:Array):Boolean{
return element[property] == value;
});
};
Array.prototype.setPropertyIsEnumerable("find", false);
最後の行のsetPropertyIsEnumerableが重要です。これがないと配列をfor ~ inでまわしたときに”find”という身に覚えのない要素が追加されてしまいます。
■ 非Dynamicなオブジェクトでの拡張
上記ソースのようにDynamicなArrayを拡張した場合、arr.find(“age”,20)のようにObj.func()という形で拡張した関数を呼び出すことができます。しかし、以下の用にDynamicではないStringを拡張したときにstr.camelize()を呼ぼうとするとコンパイル時にエラーになってしまいました。
String.prototype.camelize = function():String{
var tmp:String = "";
for each (var element:String in this.split('_')){
tmp += element.charAt(0).toUpperCase() + element.substr(1);
}
return tmp;
};
コンパイルエラーを防ぐには、かっこわるいですが、str[‘camelize’]()の様に呼び出せば良いようです。本当はStringをDynamicにしないといけないのかもしれませんが、低レベルのクラスをいじるのは気が引けるのでこの方法を使っています。
さて、以上2点、私のように見切り発車でコーディングをしてしまうとはまってしまうこともあると思い紹介してみました。なにかのご参考になればうれしいです。