2

コンストラクターを呼び出すたびに再定義されないJavascriptプライベートメソッドをどのように作成しますか?

私の知る限り、OOP-JSでは、プライベートメソッドは、新しい「オブジェクト」をインスタンス化するたびに呼び出される、自分の「クラス」の「コンストラクターメソッド」で定義されたメソッドです。関数宣言(つまりfunction name()、関数式ではなくvar name = function())でうまくいくと思っていましたが、次のコードで関数を1回だけ宣言するようにするにはどうすればよいですか?

​function Tester() {
    function test () {
        console.log("executed");
    }
}
var t1 = new Tester();
var t2 = new Tester();
4

2 に答える 2

4

コンストラクターを呼び出すたびに再定義されないJavascriptプライベートメソッドをどのように作成しますか?

あなたはできません(まあ、少し小刻みに動く部屋については以下を参照してください)。ただし、のインスタンスが何千もある場合を除いてTester、あまり心配する必要はありません。ほとんどのエンジンは、作成される複数の関数オブジェクト全体で基礎となるコードを再利用する可能性があります。(コード、マインド。関数オブジェクトやそれが閉じるコンテキストではなく、毎回一意で割り当てられる必要があります。ただし、大きくする必要はありません。もちろん、かなりの関数関数もかなり小さいです...)

...次のコードで関数が1回だけ宣言されていることを確認するにはどうすればよいですか?

あなたはそれがそうではないと確信することができます。Tester呼び出されるたびに関数を宣言します。目撃者:

​function Tester() {
    this.test = test;
    function test () {
        console.log("executed");
    }
}
var t1 = new Tester();
var t2 = new Tester();
console.log(t1.test === t2.test); // "false"

実装にプライベートであるが、オブジェクトのどのインスタンスにも割り当てられていない関数を持つことができることに注意してください。モジュールパターンは、それを行うのに便利です。

var Tester = (function() {

    function Tester(name) {
        this.name = name;
    }
    Tester.prototype.publicFunction = function() {
        privateFunction.call(this);
    };

    function privateFunction() {
        console.log("My name is " + this.name);
    }

    return Tester;
})();

var t = new Tester("Fred");
t.publicFunction(); // Outputs "My name is Fred" via the private function

そこでprivateFunctionは完全にプライベートであり、無名関数内のコードにのみアクセスできます。Testerまた、そのコピーは1つだけですが、を使用してインスタンスのメソッドを呼び出しているかのように呼び出すことができますprivateFunction.call(this)

あるいは、もちろん、使用callは通常の呼び出しを行うよりも少し遅いので、インスタンスを引数として渡すことができます。

var Tester = (function() {

    function Tester(name) {
        this.name = name;
    }
    Tester.prototype.publicFunction = function() {
        privateFunction(this);
    };

    function privateFunction(t) {
        console.log("My name is " + t.name);
    }

    return Tester;
})();

var t = new Tester("Fred");
t.publicFunction(); // Outputs "My name is Fred" via the private function

もちろん、の追加コストは、callそれが問題である場合にのみ問題になります。タイトなループで何十万回も電話をかけているのでない限り、それが問題になることはまずありません。したがって、引数を使用するcallthis渡すかは、主にスタイルの選択になります。

于 2012-05-05T15:27:16.913 に答える
2

しばらく時間がかかりましたが(ActionScript 3のバックグラウンドから)、心配するのをやめ、プライベートメソッドの欠如を愛するようになった方法を皆さんと共有する必要があると思います;)

Backbone.jsjs-Signalsなどの多くの一般的なJavaScriptライブラリは、わずかに難解な構文を使用するのではなく、先頭の下線がプライベートメンバーを示す命名規則を使用しています(それぞれ独自のものです!)。これにいくつかの追加のコンテキストを与えるために、Pythonのドキュメントは、Pythonがプライベートメンバーをまったくサポートしていないと述べており、代わりにアンダースコアを使用することを提案しています

JavaScriptは非常に動的な言語です。厳密な型チェックはなく、非常にエキサイティングなスコーピングがいくつかあります。そして、これらの事実を利用する本当にクールなライブラリがいくつかあります。たとえば、コードベースで意味のあるテストカバレッジを簡単に実現できるSinonJSなどです。例えば:

var instance = new Car("ford");

// Replace the car's engine with test stub.
// Alternative syntax: sinon.stub(instance, '_engine');
instance._engine = sinon.stub(instance._engine);

car.start();

// As the '_engine' object has been mocked it gains new attributes.
ok(instance._engine.checkOil.calledOnce, 'Oil level was checked');

申し訳ありませんが、この回答は実際にはあなたの質問に答えていません(TJの回答はその点でほとんど教科書です)-私は別の可能な解決策を提供する価値があると思っただけです。

于 2012-05-05T18:10:27.547 に答える