prototype test

by matacat
=========================================================
Refer to
「ActionScript の Object.prototype を拡張する実用的な例」
http://d.hatena.ne.jp/amachang/20061220/1166635804
よくわかってないんですが、 dynamic じゃないクラスの prototype を
いじる時は setPropertyIsEnumerable で false を指定しないと
いけないのでしょうか? true のままだとランタイムエラーになります…
なんかダイナミックにプロパティを追加しようとしてるみたいで
-----------------------------------------------------
わかりました。 _def や_merge を enumerable にしちゃうと
_merge 関数内の for in で列挙され、静的クラスで使用した場合に
ダイナミックにプロパティを追加しようとしてしまうんですね…
なぜ気付かない俺 orz
まあそもそも enumerable にしませんよね普通。
=========================================================
♥0 | Line 27 | Modified 2010-03-03 11:20:49 | MIT License
play

ActionScript3 source code

/**
 * Copyright matacat ( http://wonderfl.net/user/matacat )
 * MIT License ( http://www.opensource.org/licenses/mit-license.php )
 * Downloaded from: http://wonderfl.net/c/uQZU
 */

//=========================================================
//
//  Refer to
//  「ActionScript の Object.prototype を拡張する実用的な例」
//  http://d.hatena.ne.jp/amachang/20061220/1166635804
//
//  よくわかってないんですが、 dynamic じゃないクラスの prototype を
//  いじる時は setPropertyIsEnumerable で false を指定しないと
//  いけないのでしょうか? true のままだとランタイムエラーになります…
//  なんかダイナミックにプロパティを追加しようとしてるみたいで
//  -----------------------------------------------------
//  わかりました。 _def や_merge を enumerable にしちゃうと
//  _merge 関数内の for in で列挙され、静的クラスで使用した場合に
//  ダイナミックにプロパティを追加しようとしてしまうんですね…
//  なぜ気付かない俺 orz
//  まあそもそも enumerable にしませんよね普通。
//
//=========================================================

package
{
    import flash.display.Sprite;
    import flash.text.TextField;
    import flash.text.TextFormat;
    
    public class PrototypeTest extends Sprite
    {
        public function PrototypeTest()
        {
            var m:String = "_merge";
            var t:TextField;
            
            // コンパイラが strict モードだと "." で _def や
            // _merge を呼び出すことができないので "[]" を使う。
            
            addChild(t = new TextField()[m]( { type: "input", defaultTextFormat: new TextFormat(null, 20), wordWrap: true, multiline: true, border: true, x: 10, y: 10, width: 445, height: 445, text: "いちぎょーん" } ));
            
            // for in で _def や _merge は列挙されるかな?
            
            for (var i:String in t) t.appendText(i);
            
            // されません。
        }
        
        // Object クラスの prototype にプロパティやメソッドを追加する
        // ことで、ありとあらゆるあらゆるインスタンスがあたかもそれらを
        // 所有しているかのようにふるまうことができる。
        // 便利な半面、呼び出しに時間がかかる。頻繁に呼び出される
        // メソッドはクラスで定義しましょう。もしくはバインドしちゃうとか?
        // ビルトインクラスを拡張したいときはこの手法。
        
        // _def は prototype を介して呼び出すことで、新しく
        // プロパティやメソッドを追加すると同時にそれらを
        // not enumerable にするメソッド。
        
        Object.prototype._def = function(p:String, o:*):void
        {
            this[p] = o;
            this.setPropertyIsEnumerable(p, false);
        };
        Object.prototype.setPropertyIsEnumerable("_def", false);
        
        // _merge は いろんなプロパティを持つインスタンスに対し
        // オブジェクトを一個だけ渡してそれらを一気に設定しちゃうメソッド
        
        Object.prototype._def("_merge", function(o:Object):*
        {
            for(var p:String in o) this[p] = o[p];
            return this;
        });
        
        // Object クラスの prototype にプロパティやメソッドを追加したら
        // 必ずそれらを not enumerable にしましょう。
    }
}