6

私はこのコードを持っています:

var Human=function(name){
  this._name=name;
};
Human.prototype.Shout=function(){
  alert(this._name);
};

var tom=new Human("tom");
var john=new Human("john");
alert(tom.Shout===john.Shout);

現在、._nameは「プライベート」ではありません。._nameを「プライベート」にしたいのですが、同時に、Humanのインスタンスごとに追加の関数を作成したくありません(つまり、tom.Shoutはjohn.Shoutに対して===である必要があります)。各インスタンスは問題ありません..不要です(オフトピックです-これについては別のスレッドで議論できます)

私の結論は、私が達成しようとしていること(._nameを「プライベート」にすると同時にtom.Shout===john.Shout)は不可能であるということです。

しかし、結論に飛び込む前に、200%確実になりたいと思っています。

(要件が満たされている限り、つまりインスタンスごとに追加の関数を作成しない限り、ハッキングを歓迎します)

スコープを実行するために追加の関数を作成する必要がある場合、それは問題ありませんが、その数は固定数である必要があり、Humanのインスタンスが追加されるたびにその数が増えることはありません。

4

3 に答える 3

3

アップデート

@nameインスタンス変数を探しています。es.nextにあることを祈ってください、しかし私たちはまだそれを持っていません。多分2年で。

クリーンなAPIを気にするなら、ここにあなたの解決策があります:

function Class(foo) {
    Class.priv(this).foo = foo;
}

Class.priv = (function() {
    var cache = [],
        uid = 1;

    return function(obj) {
        if (!this.__id) {
            this.__id = uid;
            cache[uid++] = {};
        }
        return cache[this.__id];
    };

}());

Class.prototype.bar = function() {
    console.log(Class.priv(this).foo);
}

コンストラクターの関数として、すべてのデータをキャッシュに保管します。オブジェクトにデータが乱雑になることはありません。

オリジナル

しかし、「プライベート」というものはありません。

できることは、関数内にローカル変数を作成することだけです。

コンストラクター関数

var Human = function(name) {
    // local variable.
    var _name = name;
}

ローカルであることの定義により、コンストラクター関数の外部では使用できないローカル変数があります。

これは、プロトタイプのような外部コードでアクセスできないことを意味します。

ただし、ES5を使用して読み取り専用にすることができます。

var Human = function(name) {
    Object.defineProperty(this, "name", { value: name });
}

あなたが本当にあなたの求めていることを達成することができれば、あなたはjsで大きな進歩を遂げるでしょう。私は何時間もそれをやろうとしました。

別のパターンは次のようになります:

var Human = function(name) {
   this.name = name;

   return {
       Shout: this.Shout.bind(this)
   };
}

Human.prototype.Shout = function() {
   console.log(this.name);
}

.bindただし、これには、インスタンスごとに新しいオブジェクトを呼び出して作成するオーバーヘッドがあります。

于 2011-05-13T23:33:13.420 に答える
1

これはどう ?

    var Human = function (name) {
        var _name = name;

        this.getName = function () {
            return _name;
        }
    };
    Human.prototype.Shout = function () {
        alert(this.getName());
    };

    var tom = new Human("tom");
    var john = new Human("john");

    tom.Shout(); // tom
    john.Shout(); // john
    alert(tom.Shout === john.Shout); // true

編集:前者はGETプロパティ用に別の関数を作成しますが、追加の関数を作成しないと不可能です。

于 2011-05-13T22:46:30.940 に答える
1

質問を読みましたが、理解できthis._nameませんでした。プライベートではないため、質問は少し奇妙です。これが私のテストでプロトタイプメソッドが一度追加され、すべてのインスタンスで利用できるようにする方法です。繰り返しますthis._nameが、ここでは非公開ではありません。ローカル変数を追加し、プロトタイプメソッドのクロージャを介してアクセスしたい場合、ローカル変数の値を呼び出すと、すべてのインスタンスで同じ値になります。

とにかく、このコンストラクター関数を使用すると、this._name getterメソッドとshoutメソッドがプロトタイプチェーンに一度追加されるため、Humanのすべてのインスタンスで使用できます。

function Human(name) {
    if (!(this instanceof Human)){
        return new Human(name);
    }
    this._name = name;

    if (!Human.prototype.Name){
         Human.prototype.Name = function(val){
            if (val){
               this._name = val;
               return this;
            }
            return this._name;
          };
          Human.prototype.shout = function(){
              alert(this._name);
          }
    }
}
于 2011-05-13T23:50:37.360 に答える