web-dev-qa-db-ja.com

JavaScriptインスタンス関数とプロトタイプ関数

重複の可能性:
Javascriptでの「プロトタイプ」と「これ」の使用?

さまざまな種類のJavaScript関数についての私の理解は次のとおりです。

function MyObj() {
    this.propOne = true;
    this.publicInstanceFunc = function() {
        if (propOne)
            return 'public instance function';
    }
    function privateFunc() {
        return 'private function only visible inside this constructor';
    }
}

MyObj.prototype.protoFunc = function() {
    if (this.propOne)
        return 'prototype function shared amongst all instances of MyObj';
}
  1. これらは正しいですか?
  2. プロトタイプ(例:protoFunc)とコンストラクター(例:publicInstanceFunc)に関数を配置する必要があるのはどのような場合ですか?
  3. プロトタイプ関数内のプロパティにアクセスするための正しい方法はthisを使用していますか?
29
mcjabberz

全体を自己実行関数でラップすることにより、実際に別のレベルの特権を追加できます。

var MyObj = (function() { // scoping
    var privateSharedVar = 'foo';

    function privateSharedFunction() {
        // has access to privateSharedVar
        // may also access publicSharedVar via explicit MyObj.prototype
        // can't be called via this
    }

    function MyObj() { // constructor
        var privateInstanceVar = 'bar';
        this.publicInstanceVar = 'baz';

        function privateInstanceFunction() {
            // has access to all vars
            // can't be called via this
        };

        this.publicInstanceMethod = function() {
            // has access to all vars
            // also known as a privileged method
        };
    }

    MyObj.prototype.publicSharedVar = 'quux';

    MyObj.prototype.publicSharedMethod = function() {
        // has access to shared and public vars
        // canonical way for method creation:
        // try to use this as much as possible
    };

    return MyObj;
})();

thisを介して外部からアクセスできるのは、「public」プロパティのみです。

パフォーマンス上の理由から、「インスタンス」メソッドと呼ばれるものは避ける必要があります。これらのそれぞれについて、MyObjectインスタンスごとに新しい関数オブジェクトを作成する必要がありますが、「共有」メソッドごとに1つの関数オブジェクトしかありません。

51
Christoph

これらは正しいですか?

エラー。まあ、それはあなたが何をしたいかによります。 JavaScriptでクラス/インスタンススタイルの継承を実装するための標準的なモデルは誰も受け入れていません。

でもこれは:

    if (propOne)

おそらく間違いです、そのthis.propOneは所有者オブジェクトのプロパティですが、propOne自体は宣言されていない変数です(これはデフォルトでグローバル変数になりますが、通常は誤りです)。

プロトタイプ(例:protoFunc)とコンストラクター(例:publicInstanceFunc)に関数を配置する必要があるのはどのような場合ですか?

プロトタイプに設定された関数は、すべてのオブジェクト間で共有される同じ関数です。所属するインスタンスを特定する唯一の方法は、呼び出されたときに「this」を読み取ることです。

コンストラクターの「this」に設定された関数は、MyObjのすべてのインスタンスの新しい関数です。これを「this」の代わりにクロージャに基づいて所有者オブジェクトにバインドする別の方法として使用できる可能性があります。これにより、関数バインディングのものを書き出す手間を省くことができます。これは、通常はこのベースのスタイルと混合しない、異なるスタイルのオブジェクト指向です。

4
bobince

1)はい、あなたのコードは正しいです。

2)コンストラクター関数自体のスコープ内でプライベートに定義された他のメンバーにアクセスする場合、たとえば、 特権メソッド を作成する場合は、コンストラクター関数内で定義された関数を使用します。

コンストラクター関数で定義されたパブリック関数は、オブジェクトプロトタイプに単純な関数を追加するよりも計算コストが高くなりますが、柔軟性も大幅に向上します。

3)はい、プロパティがパブリックの場合、thisはオブジェクトのインスタンスを参照するため、プロトタイプ拡張関数内でthisキーワードを使用してアクセスできます。

3
CMS

2番目のポイントに関しては、プロトタイプを拡張して、すでに作成されているすべてのオブジェクトが新しいメソッドを取得するようにします。

また、組み込みオブジェクトにメソッドを追加できます(trim()stringに追加するなど)。

3
Esteban Küber