これまたマニュアルに載ってない、関数の設定をするASSetPropFlagsという関数の話です。

なんでコレを書くにいたったかというと、以前のビルトインクラスや関数拡張系のハックを行った際に不都合が出てくるからです。

まず該当するエントリーは以下です。

何がいけないかというと、Class.prototypeなどにプロパティを追加するかたちで拡張した場合、そのままだと拡張したメソッドがプロパティとして紛れ込んだ状態になります。
そのため、for inなどでプロパティを洗い出したときなどにユーザにとって予期しないプロパティも列挙されることになってしまいます。

特にArray、Object、MovieClipなどダイナミックにプロパティを増やせるクラスで陥りやすい問題です。

Array.prototype.hoge = function () { trace("hoge"); } var test = new Array( "aaa", "bbb" ); for( var i in test ) { trace( "i" + test[i] ); }

/// Trace出力 hoge:[type Function] 1:bbb 0:aaa

これではデータを扱うのに非常に不便です。
個人で一時的に拡張する場合はあまり問題にならないかもしれませんが、ライブラリとして配布したりされたりする場合では、ほかのfor inなどを用いた重要な処理があると干渉してしまい予期せぬエラーに陥ってしまいます。

具体的にはArray.prototypeの拡張をした上でFuseKitエンジンを使うとうまく動かなくなりました。

さて、これを避けるためにASSetPropFlagsの出番です。
ASSetPropFlagsは、あるプロパティについて上書き、削除、隠す、の3つの項目を設定できる関数です。

ASSetPropFlags( Object, Properties, n, allowFalse );

  • Object : 対象となるオブジェクトへの参照
  • Properties : 設定したいプロパティ名のストリングまたは配列
  • n : 設定をTrueにするためのビットマスク( 上書き| 削除 | 隠蔽 )
  • allowFalse : 以上の設定を上書きさせるかどうかのBoolean値

ここでは拡張した関数をプロパティではなくメソッドとして振舞えるよう「隠蔽」フラグをtrueにします。

Array.prototype.hoge = function () { trace("hoge"); } ASSetPropFlags( Array.prototype, "hoge",1 ); var test = new Array( "aaa", "bbb" ); for( var i in test ) { trace( "i" + test[i] ); }

/// Trace出力 1:bbb 0:aaa

これでほかのメソッドと同じようにプロパティとして列挙されなくなりました。

ビットフラグ一覧表
上書き削除隠蔽2進数10進数
truetruetrue1117
truetruefalse1106
truefalsetrue1015
truefalsefalse1004
falsetruetrue0113
falsetruefalse0102
falsefalsetrue0011
falsefalsefalse0000

また注意するポイントはprototypeを拡張した場合(つまりインスタンスメソッドの場合)、ターゲットとなるオブジェクトにSomeObject.prototypeを渡す必要があります。

ちなみに、すでにObjectの長さを取得するでも触れています。

という感じで。拡張する場合はもとの大事な部分を汚染しないよう心がけましょう。

HTML5飯