2

ModulePatternやRevealingModulepattenのような「クラス」タイプのJavaScript関数を書き始めました。これにより、「new」の使用が回避され、どの関数が1か所で公開されるかを定義できます。ただし、このパターンでパブリックデータメンバーを使用およびアクセスする方法を確認できませんでした。

たとえば、以下のメンバー'id'はmyobj.getId()からアクセスできますが、myobj.idは未定義です。

function setup(){
    var myobj = MyObject();
    myobj.initialize();
    alert(myobj.getId()); // returns 3, as expected
    alert(myobj.id); // returns undefined
}
function MyObject(){
    var id;
    function initialize(){
        //do some stuff that initializes data including...
        id = 3;
    }
    return{
        initialize:initialize,
        id:id,
        getId:function(){ return id;}
    }
}

initialize()で設定された値を返すようにmyobj.idを機能させる方法はありませんか?

4

3 に答える 3

3

あなたの問題は、あなたがクロージャを利用していないということです。この行id:idは、返すオブジェクトリテラルのメンバーとして新しい変数を作成します。これにはデフォルト値がありますundefined。次に、同じ変数idをそれ自体にundefined再度割り当てます。

また、モジュールは単一のオブジェクトインスタンスであり、ファクトリ関数ではありません。次のようなものを試してください。

var myModule = (function(opts) {
    var foo = opts.foo || 0,    //private variables with default values
        bar = opts.bar || 0,    // if none are passed in

        product = function() {      //private method
            return (foo * bar);
        };

    return {
        getFoo : function() {   //public methods
            return foo;
        },
        fooTimesBar : function() {
            return product();
        }
    }
})({
    foo : 5,                    //options object
    bar : 7
});

モジュールパターンのコアは、変数を宣言し、クロージャを介してそれらの変数への特権アクセスを持つオブジェクトを返す自己実行無名関数です。

最後の追加の括弧は、ここに渡されるいくつかのオプションを含むオブジェクトリテラルを含み、関数を実行します。次に、オブジェクトを返し、それをに割り当てますmyModule

その返されたオブジェクトのメンバーとして宣言されたものはすべて、パブリックにアクセスできます。返されたオブジェクトのコードは、関数が返された後でも、クロージャを介して無名関数で定義された変数にアクセスできます。無名関数で宣言された変数は事実上プライベートです。関数外のコードは、返されたオブジェクトで提供されるメソッドを介さない限り、それらをアドレス指定できません。

全体として、。の単一のオブジェクトインスタンスになりmyObjectます。モジュールの定義である1つしか作成できません。ただし、同様のアプローチでファクトリ関数を作成することもできます。

于 2010-07-15T18:17:36.787 に答える
1

その理由は、変数がデフォルトでにid設定されており、そのタイプも同様になるためです。これで、未定義の型はプリミティブな型であるため、返されるオブジェクトでの割り当ては、参照ではなく値の割り当てになります。したがって、インスタンスになり、コンストラクター関数の変数と同じにはなりません。undefinedundefinedobj.idundefinedid

ここで、コンストラクター関数のinitializeを変更し、同じを返しますが、オブジェクトプロパティを参照します。idgetIdidobj.idundefined

function MyObject(){
    // initialize is used as a public function so
    // this will always refer to the current instance
    function initialize(){
        this.id = 3;
    }
    return {
        // no need to define id here it will 
        // report undefined on access by default
        initialize: initialize,
        getId:function(){ return this.id; }
    }
}

すべてを実行して、期待どおりに機能することを確認します。</ p>

于 2010-07-15T16:45:12.867 に答える
0

これを解決し、匿名オブジェクトの代わりにキャッシュされたオブジェクトを返すことで、Revealingモジュールパターンの構文糖衣を維持できます。

例えば:

NAMESPACE.Module = (function () {

    //All public members go on api
    var api = {}
    api.id = 3;

    //Private members
    var self,
        foo,
        bar;


    /**
        @public
    */
    api.init = function () {
        self = this;
        console.log(this); //NAMESPACE.Module
    }


    /**
        @private
    */
    function _privateFunction() {
        console.log(self); //NAMESPACE.Module
    }

    return api;
}());
于 2012-05-25T09:25:16.910 に答える