1

このコードのJavaScriptコードを想定

(function(){

NameSpace = new function(){} //global namespace

NameSpace.Apple = function(p_color){
  var AppleInstance = this; //clarity..

  AppleInstance.color = p_color;

  return {
    /**************
    / Public method
    /**************/
    //Here, we only return an access to the Method Eat
    Eat : NameSpace.Apple.prototype.Eat
  }
}

//Will be public
NameSpace.Apple.prototype.Eat = function(){
  var AppleInstance = this; //clarity..

  console.log("I'm eating a " + AppleInstance.color + " apple !")
}

//Will be private
NameSpace.Apple.prototype.PrivateMethod = function(){
  var AppleInstance = this; //clarity..

  console.log("This is a private method");
}

})()

new NameSpace.Apple("blue").Eat();
//I'm eating a undefined apple !

ご覧のとおり、1 つのプライベート変数、1 つのプライベート メソッド、および 1 つのパブリック メソッドを含む名前空間にクラスがあります。しかし、私のパブリックメソッドにアクセスするとき、これはクラスの変数にアクセスできません。

私はこれが原因であることを知っています:

return {
    /*...*/
}

しかし、私のパブリック プロトタイプ メソッドがプライベート変数にアクセスする方法はありますか (元のコードでは定数が必要です)。

リターンでプロパティを返す場合、プロトタイプ メソッドはそれにアクセスできますが、それ以外の場合はアクセスできません。

ありがとう。

4

2 に答える 2

3

いいえ。2 つの戦略はやや互換性がありません。これが、プライベート プロパティが通常パブリックである理由ですが、プロトタイプを使用する場合はアンダースコアが前に付けられます。

Namespace.Apple = function(p_color){
  this._color = p_color;
};

Namespace.Apple.prototype.eat = function(){
  console.log("I'm eating a " + this._color + " apple !")
};

_colorこれは、このコードを使用する JS 開発者に、内部使用のためのプロパティであるため、プロパティをいじってはならないことを伝えます。


とはいえ、ここには他にも大きな問題があります...

Namespace.Apple = function(p_color){
  var AppleInstance = this; //clarity..

  AppleInstance.color = p_color;

  return {
    /**************
    / Public method
    /**************/
    //Here, we only return an access to the Method Eat
    Eat : NameSpace.Apple.prototype.Eat
  }
}

これはあなたが思うようにはなりません。コンストラクターがオブジェクトを返すと、作成されたインスタンスnewは破棄されます。したがって、のインスタンスにはなりませんApple。代わりに、次のような単純なオブジェクトを取得します。

{ Eat: Namespace.Apple.prototype.Eat }

色を割り当てたオブジェクトは?なくなった。


このメソッドはプライベートではありません。

//Will NOT be private
Namespace.Apple.prototype.PrivateMethod = function(){
  var AppleInstance = this; //clarity..
  console.log("This is a private method");
}

プロトタイプのすべてが公開されています。すべての。


そして、慣習についてのメモ。

var AppleInstance = this; //clarity..

私はまったく明確ではないと思います。 thisインスタンスメソッドでインスタンスを意味するために使用されthisます。それを難読化すると、読みやすさ損なわれます。

また、読みやすさのために、コンストラクターの大文字の変数名 (Eat悪い!、Apple良い!、AppleInstance悪い!) を保存してください。キーワードなしでコンストラクターを呼び出すと、newいくつかの奇妙な結果が生じる可能性があります。


これを回避し、プライベート変数とメソッドを保持するには、プロトタイプをまったく使用しません。すべての変数とメソッドをコンストラクター内から関数として設定し、インスタンスを 1 つずつ作成します。

var Namespace = {};
Namespace.Apple = function(color){
  // color form the arguments is a local variable, bound to the methods created below
  var somePrivateVar = 'privateData!'; // private instance variable

  // public method, with access to private instance vars
  this.eat = function(){
    console.log("I'm eating a " + color + " apple!");
  };

  // public method, which calls private method
  this.doSomethingPrivate = function() {
    console.log('calling private method for you');
    privateMethod()
  }

  // private method
  var privateMethod = function(){
    console.log("This is a private method for a " + color + " apple!");
  };

  // instance is auto-returned, no return needed.
}

var apple = new Namespace.Apple('red');
apple.eat();                // I'm eating a red apple!
apple.doSomethingPrivate(); // calling private method for you
                            // This is a private method for a red apple!
apple.privateMethod()       // <exception> apple.privateMethod is undefined

このアプローチについて注意すべき点は、プロトタイプを使用する場合よりもはるかに遅くなり、より多くのメモリを使用する可能性があることです。プロトタイプの関数はすべてのインスタンス間で共有されるため、メソッドに対して 1 つの関数を作成して保存するだけで、すべてのインスタンスがその関数オブジェクトを実行します。

上記のアプローチでは、すべてのインスタンスが各メソッド関数の新しいコピーを作成して保存します。また、各関数には、そのインスタンス コンストラクターのスコープへの特権アクセスがあり、プライベート変数とメソッドを使用できます。少数のインスタンスのみを計画している場合、この違いは大きな違いにはなりません。ただし、非常に多数のインスタンスを計画している場合は、パフォーマンスの違いが非常に重要になる可能性があります。

于 2013-06-20T18:41:04.590 に答える