2011/04/17

JavaScript の Private メンバ

■問題
JavaScriptの文法上、直接オブジェクトのprivateメンバを指定することはできません。とはいえ、Douglas Crockford氏が「Private Members in JavaScript」で書かれている通り、JavaScriptで privateメンバが実現できないわけではありません。明示的に書けるようにされた方もいます。
しかし上記の方法ではオブジェクトの生成に「new」を使用しています。JavaScriptの「new」はちょっと厄介な仕組みになっていますので、出来れば使いたくありません。

■解案
同じく Douglas Crockford氏の著書「JavaScript: The Good Parts ―「良いパーツ」によるベストプラクティス」では、「new」を使用しない仕組みも紹介されています。個人的にちょっと理解し難かったので、その方法を纏めてみました。

    var function createMyObject(inInitArg){
        // 1. Create private members
        var privateVariable = inInitArg;
        var privateFunction = function(){
                    :
                    :
        };

        // 2. Create a new empty object.
        var that = {};  

        // 3. Add propery to the new objet as its public members.
        that.publicVariable = 0;
        that.publicFunction = function(inFuncArg){
                    :
                    :
            // Use Private Members
            privateVariable = inFuncArg * 2;
            var ret = privateFunction();
                    :
                    :
        };
    
        // 4. Return the obuject as MyObject
        return that;
    };

■若干の解説
createMyObject()内の処理は以下の通り。
  1. privateメンバとなる変数/関数を定義する
  2. まっさらのオブジェクト「that」を作成する
  3. 「that」にプロパティを追加してMyObjectのインスタンスにする
  4. 完成した「that」 を返却する
クロージャを利用して、createMyObject()関数内のコードからは、private メンバにアクセスできるようになっています。privateメンバの呼び出し時に、「this.」がないのがポイントです。
これで、「new」を排除することができました。(^o^)

■継承
別のオブジェクト(クラスではない!)を継承したいときは、「var that = {};」 の部分を
var that = createMyParentObject();
としてあげれば良いです。

■欠点
JavaScriptの「prototype」機能を活用出来ていません。
複数のMyObjetインスタンスを作成した場合、共通で使えるはずのpublicFunction()関数オブジェクトのインスタンスもその数分、作成されてしまいます。大量にオブジェクトを生成する場合は注意が必要です。

0 件のコメント:

コメントを投稿