10

JavaScriptでは、コンストラクターで宣言することにより、プライベートメソッドと特権メソッドを作成できます。これにより、オブジェクトのプロトタイプからそれらを移動する必要があります。次に、すべてのオブジェクトが1つのプロトタイプオブジェクトにアクセスする代わりに、それらのメソッドの独自のコピーを持つため、継承の可能性とパフォーマンスが失われます。

ですから、私の質問は、ペッターパターンとは何かということです。プライベートメソッドと特権メソッドを使用するかどうかです。私はぶら下がりの大ファンではないので、これを避けたいと思います。じゃあ何をすればいいの?

あなたの経験は何ですか?

4

7 に答える 7

5

JavaScript でいわゆる「プライベート」関数を作成することに価値があるとは思いませんでした。それらがパブリック API の一部ではないことを示すために何らかの方法でマークするだけです。そのため、API クライアントは、関数が存在すること、または将来のバージョンで同じ実装を持つことが保証されません。

API の一貫性は別として、必要に応じてプライベート関数を使用させない理由はありません。確かに、共存するスクリプトがプライベート関数をいじることができますが、それらのスクリプトはパブリック API 関数を既にオーバーライドしている可能性があります。

この質問に対する受け入れられた回答には、これに関する良い解説があります: 名前空間付きの JavaScript のプライベート関数

于 2011-01-30T01:32:11.913 に答える
4

慣例では、必要なものをスコープアウトします...そして、疑似プライベートまたは保護されたメンバーがメソッドまたはプロパティの前にアンダースコアを付けるようにします。

私は疑似プライベート/保護スコープを好みます...

var MyObject = (function(){
  var interalStaticVar;

  function ctor(arg1, arg2) {
    //create psuedo-protected context
    this._ = {};

    //create a psuedo-private context
    this.__ = {};

    //stash someval
    this.__.someVal = "hands off";
  }

  ctor.prototype.getSomethingPrivate = function() {
    return this.__.someVal;
  }

  ctor.prototype._doSomethingProtected = function(){ ... }

  ctor.prototype.__doSomethingPrivate = function() { ... }

  return ctor;
}());

OOスタイルの継承パラダイムをJavaScriptに適用しようとすると、問題が発生し、おそらく何か間違ったことをしていることを意味します。私は、ブラウザーでJSの機能イベント駆動型の性質を取り入れたより多くのSOLID設計に従う傾向があります。

于 2011-01-30T09:49:03.210 に答える
3

を使用して、プライベートまたは内部のメソッドとプロパティをエミュレートできます。

obj._foo = private;

obj.prototype._internalMethod;

プライベート メソッドを継承から分離する必要があります。継承に依存せずに使用できるものはすべて正常に機能します。また、次のようなパターン:

function construct() { 
    var priv;

    this.someValue = foo;
    this.someMethod = function() { }
}

ここでは、プロトタイプを無視して、オブジェクトに直接書き込みます。メソッドと変数を非表示にするためにクロージャーに依存するこのパターンは、ミックスインでうまく機能します。

コンストラクターでのメソッドの再宣言が非効率的ではないかと心配するのは、マイクロ最適化とです。少なくとも 1000 個のオブジェクトを作成する予定がない場合、違いはごくわずかです。

于 2011-01-30T01:44:12.427 に答える
3

コンストラクターで使用されているが、パブリック API の一部ではない関数がいくつかあると推測します。

この場合、1 つのオプションは、それらをコンストラクターのプロパティとして単純に格納することです。次に、コンストラクターでそれらを呼び出すときに、.call()メソッドを使用して、構築中の現在のオブジェクトのコンテキストを設定します。

このようにして、自動的に を介してパブリック メンバーにアクセスしthis、引数として渡すとプライベート変数にアクセスできます。

var myClass = function() {
    this.someprop = 'prop value';
    var privVar = 'private value';

    myClass.func.call(this, privVar);
};

myClass.func = function(priv){ 
    alert(this.someprop);
    alert(priv); 
};

var inst = new myClass;

したがって、これはMyClass、コンストラクターによって使用される関数の名前空間ストレージとして関数を使用するだけです。コンストラクターは、渡されたと でthis何かを行うのコンテキストからそれを呼び出します。this.somePropertyprivVar

これがあなたの求めているものかどうかはわかりませんが、それは1つのオプションです。


以下のコメントで@Raynosが正しく指摘しているように、単純な名前空間ストレージとしてコンストラクターに追加されたプロパティMyClassはまったくプライベートではなく、コンストラクターにアクセスできる任意のコードからアクセスできます。

instanceofのインスタンスから呼び出されることを確認するチェックを追加するなど、適切に呼び出されるようにするためにいくつかのチェックを行うことができますがMyClass、そのようなチェックはまったく安全ではなく、実際のプライベートメンバーの保護を提供しません。

于 2011-01-30T01:55:40.073 に答える
2

それはすべて、オブジェクトをどのように使用したいかによると思います。あるオブジェクトにプライベート変数/関数が必要で、そのオブジェクトのプロトタイプ メソッドからアクセスできるようにしたい場合はコンストラクター内でプロトタイプ メソッドを宣言する必要があります (こちらのを参照)。

私の意見では、それはプログラムの設計と使用法に帰着します。本当にプライベートな変数や関数を持つオブジェクトが必要な場合は、私が示した例のように設計してください。そうでない場合は設計しないでください。私の経験では、プライベート/特権機能は実際にはパフォーマンスに影響を与えていません。

于 2011-01-30T10:37:22.090 に答える
0

私は通常、javascript オブジェクトを作成する際に次のパターンに従います。

var builders = (function() {
var privateMethod = null;
function builders() {
            this.a_priviledged_method = function() {};
            this.pointerToPrototypeMethod = __bind(this.prototypeMethod, this);
    }
    builders.prototype.prototypeMethod = function(){};
    return builders;
})();
// general method to bind a function call to a context
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };

注意点:

  1. 「privateMethod」は、コンストラクター内にないという意味ではプライベートではありませんが、スコープを設定することで、作成されるビルダーの各インスタンスに対してプライベートにすることができます。
  2. プロトタイプメソッドが、「呼び出された」コンテキストではなく、「作成された」コンテキストで呼び出されるようにします。作成時のコンテキストでプロトタイプメソッドをカリー化した疑似特権メソッドを作成しました。プロトタイプ メソッドへの後続の呼び出しは、作成時のコンテキストで常に発生します。
  3. javascript のメソッド ルックアップ メカニズムでは、プロトタイプ チェーンを最後にチェックする必要があるため、「pointerToPrototypeMethod」は「prototypeMethod」の前に「検出」されます。
  4. 「a_priviledged_method」と同様の「pointerToPrototypeMethod」を実装することもできますが、その場合、各「builders」インスタンスには特権メソッドの独自のコピーがあり、コードのコピーが発生します。
  5. プライベート メソッドを呼び出すときは、コンテキストを提供して呼び出す必要があることを確認する必要があります。たとえば、「a_priviledged_method」の本体で「privateMethod」を呼び出したい場合は、privateMethod() として呼び出すのではなく、privateMethod.apply(this,args) として呼び出す必要があります。利点は、プライベートメソッドから特権メソッドを呼び出したい場合、同じコンテキスト (プライベートメソッドが呼び出されたもの) にあることです。

お役に立てれば。

于 2013-07-01T14:17:21.913 に答える
-1
(function () {
    function privateFunc () { ... }

    A.prototype.publicFunc1 = function () { ... };
    A.prototype.publicFunc2 = function () { ... };

})();

function A () { ... }

私は編集します:プライベート変数も必要な場合、これは役に立ちません。

于 2011-01-30T01:52:33.730 に答える