2011-01-30 12 views
10

JavaScriptでは、プライベートメソッドと特権メソッドをコンストラクターで宣言して作成できます。これにより、私はそれらをオブジェクトのプロトタイプから移動させなければなりません。そして、すべてのオブジェクトは1つのプロトタイプオブジェクトにアクセスするのではなく、それらのメソッドのコピーを所有するため、継承とパフォーマンスの可能性は失われます。プライベートメソッドと特権メソッドとプロトタイプメソッド

私の疑問は、今やプライベートで特権的な方法を利用しているかどうかということです。私はぶらぶらするファンではないので、私はこれを避けたい。じゃあ何をすればいいの?

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

答えて

5

私は、JavaScriptでいわゆる「プライベート」機能を作成する際に何の価値も見たことがありません。何らかの形でマークして、それらが公開APIの一部ではないことを示すようにしてください。そうすれば、APIクライアントはその関数が存在することを保証されず、将来のバージョンで同じ実装を持つことができません。

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

この質問への受け入れ答えは、この上の優れた解説があります。 Private functions in namespaced javascript

+0

名前空間は、JSの観点から共有することを前提とした良いアイデアです。また、OOスタイルの継承をエミュレートすることは、JSで使用しようとすると恐ろしいパターンです。固体はおそらくより良いですが、何も完璧ではありません。 – Tracker1

+0

小規模チームメンバー間で共有されるトップレベルの実装では、プライベートメンバーはほとんど無視できますが、分散ユーザーベースの大きなライブラリのようなものはプライベートメンバーの恩恵を受けるでしょう。 –

3

あなたは、あなたが相続からあなたのプライベートメソッドを区切る必要があり

obj._foo = private; 

obj.prototype._internalMethod; 

を使用してプライベートまたは内部メソッドとプロパティをエミュレートすることができます。継承に頼らずに使用できるものはすべて正常に動作します。また、パターンは次のようになります。

function construct() { 
    var priv; 

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

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

コンストラクタの再宣言方法が非効率であるかどうかについては、マイクロ最適化と悪いです。少なくとも1000個のオブジェクトを作成する予定がない場合、その差は無視できます。

-1
(function() { 
    function privateFunc() { ... } 

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

})(); 

function A() { ... } 

I編集:これはプライベート変数も必要としている場合は役に立ちません。

+0

-1サンプルコードが混乱しています。 private関数は 'this'または' A 'で宣言されたprivate変数にアクセスできない – Raynos

+0

別の関数でprivate変数にアクセスできた場合、privateではないでしょうか?私はこのコメントが混乱していることを知ります。 private関数はメソッドではありませんが、必要に応じてオブジェクトを渡すことができます。 – river

+1

一般的なパターンは、コンストラクタ内のプライベート変数とメソッドです。異なるクロージャ内のプライベートメソッドは、 'A'オブジェクト内のデータのいずれにもアクセスできません。 – Raynos

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コンストラクタのような単純な名前空間ストレージに追加されたプロパティは、すべてのプライベートではなく、コンストラクタにアクセスすることができる任意のコードによってアクセスすることができます。

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

+0

@Patrickdwそれは、可読性を犠牲にして、マイクロ最適化とは別に、プライベート関数とどのように違いますか? – Raynos

+1

@レイノス:あなたは頭の爪を打った。それはマイクロ最適化の可能性があり、確かに読みやすさには役立ちません。それはOPが(私が思う)何を求めて達成するために使用できるパターンです。それは必ずしも良いか悪いかは分かりませんが、使用する価値があるかどうかは、私が推測している限り最大です。 – user113716

+0

@patrickdwその場合、常に読みやすいようにしてください。あなたは後でいつでも_real_ボトルネックを手で最適化することができます。 – Raynos

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; 
}());

を疑似プライベート/保護された範囲を好む私はJavaScriptにOOスタイルの継承パラダイムを適用しようとすると、トラブルを求めて、おそらくあなたが何か間違ったことをやっている意味していることを言うだろう。私は、ブラウザでJSの機能的イベント駆動型の性質を取り入れた、より多くのソリッドデザインに従う傾向があります。

+0

あなたはよりエレガントになり、この['\ 0xff']かひどく嫌なことがあるかもしれません。 – Tracker1

2

私はそれがあなたのオブジェクトをどのように使いたいかによって決まると思います。 がオブジェクトのプロトタイプメソッドからアクセスできるようにするには、内にのコンストラクタ(example hereを参照)を宣言する必要があります。

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

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」はコンストラクタ内ではなく、それをスコープによって1がなるビルダーのインスタンスごとに、それはプライベート作ることができるという意味で、民間ではありません作成した。
  2. プロトタイプのメソッドが「作成された」コンテキストで呼び出され、「呼び出された」コンテキストでは呼び出されないようにする必要があります。私は作成時にコンテキストを使ってプロトタイプメソッドをカレー化する擬似特権メソッドを作成しました。プロトタイプメソッドへの後続の呼び出しは、作成時のコンテキストで常に発生します。
  3. javascriptのメソッドルックアップメカニズムによって、プロトタイプチェインを最後にチェックする必要があるため、 'prototypeMethod'の前に 'pointerToPrototypeMethod'が '発見'されます。
  4. 'a_priviledged_method'に似た 'pointerToPrototypeMethod'を実装している可能性がありますが、その場合、それぞれの 'builder'インスタンスはコードコピーにつながる特権メソッドの独自のコピーを持っています。
  5. プライベートメソッドを呼び出す際には、コンテキストを提供することによって呼び出される必要があります。例: 'a_priviledged_method'の本体で、 'privateMethod'を呼び出す場合は、privateMethod()として呼び出すことはできませんが、privateMethod.apply(this、args)として呼び出す必要があります。プライベートメソッドから特権メソッドを呼び出す場合は、プライベートメソッドが呼び出されたものと同じコンテキストになるよりも、利点があります。

これが役に立ちます。

関連する問題