2

さて、私は1つのシークレットと1つのメソッドを持つこのコンストラクタを持っています:

function Keeper(get) {
    var secretPower = 'wisdom';

    this.get = get ? get : function () { 
        return 'Its secret power is: ' + secretPower; 
    }
    // now this is privileged method only in case that there are no arguments?
}

ここで、2 つのインスタンスを作成します。1 つには特権メソッドがあります...

var yourKeeper = new Keeper();
yourKeeper.get();       // "Its secret power is: wisdom"

…が、もう一つは違います。それはその周りのコンテキストに触れることができますが、コンストラクターのプライベートには触れません...

var myKeeper = new Keeper(function() { 
        return 'Its secret power is: ' + secretPower; 
    });
myKeeper.get();         // ReferenceError: secretPower is not defined

...また、これは私が望むようには機能しません:

myKeeper.get = function() { 
    return 'Its secret power is: ' + secretPower; 
}
myKeeper.get();         // ReferenceError: secretPower is not defined

もちろんsecretPower、これらの場合はグローバル変数であるため、機能しません。

var secretPower = 'none';
myKeeper.get();         // "Its secret power is: none"

では、コンストラクターの外で特権メソッドを定義することは可能ですか? どのように?

evalでそれを行うことはできますか?(わかってる... 悪だ... 興味があるだけ)

4

3 に答える 3

2

JavaScript でのスコープの背後にあるまさにその考え方は、これは可能であってはならないということです。私がアドバイスするgetPrivateのは、コンストラクターのスコープ内に関数を追加し、それを使用して「プライベート」変数にアクセスすることです。

function Keeper(get) {
    var semiPrivates = {
        secretPower:'Wisdom'
    }

    this.getPrivate = function (variable){
        return semiPrivates[variable];
    }

    this.get = get ? get : function () { 
        return 'Its secret power is: ' + semiPrivates["secretPower"]; 
    }
}
于 2013-06-25T14:55:38.767 に答える
2

はい、コンストラクターの外部で特権メソッドを定義することは可能です。方法は次のとおりです。

var Keeper = (function (key) {
    function Keeper(get) {
        var private = {
            secretPower: "wisdom"
        };

        this.getPrivate = function (k) {
            if (k === key) return private;
        };

        this.get = get || defaultGet;
    }

    function defaultGet() {
        var private = this.getPrivate(key);
        return "The secret power is: " + private.secretPower;
    }

    return Keeper;
}({}));

仕組みは次のとおりです。

  1. 即時呼び出し関数式 (IIFE)を作成して名前空間を作成します。
  2. というオブジェクトを作成しますkey。このオブジェクトは、作成したばかりの名前空間に対してプライベートです。したがって、特権関数とコンストラクターのみがアクセスできます。
  3. privateコンストラクター内で、各インスタンスのプライベート状態を保持するというオブジェクトを作成します。
  4. getPrivateまた、引数を取り、手順 2 で作成したプライベート オブジェクトのみkを返す特権メソッドを作成します。したがって、特権関数のみがプライベート オブジェクトにアクセスできます。kkey
  5. オブジェクトの非公開状態にアクセスする特権関数はgetPrivate(key)、非公開状態オブジェクトを取得するために呼び出す必要があります。

注:このメソッドは、オブジェクトの非公開状態にアクセスする必要がある特権関数が複数ある場合にのみ役立ちます。さらに、この呼び出しは、getPrivate特権関数に (非常に) わずかなパフォーマンス オーバーヘッドをもたらします。


ところで、JavaScript でクリーンなオブジェクト指向コードを書きたい場合は、augmentライブラリを見てください。上記のコードは、次を使用して次のようになりますaugment

var Keeper = Object.augment(function (key) {
    this.constructor = function (get) {
        var private = {
            secretPower: "wisdom"
        };

        this.getPrivate = function (k) {
            if (k === key) return private;
        };

        this.get = get || defaultGet;
    };

    function defaultGet() {
        var private = this.getPrivate(key);
        return "The secret power is: " + private.secretPower;
    }
}, {});
于 2013-06-25T15:49:01.443 に答える