1

この質問は、JavaScript で「プライベート」インスタンス変数を持つ機能に関して解決しようとしていた問題から生じています。私の質問の前に、これを読みたいと思うかもしれません。

完全を期すために、質問をする前に、問題全体を説明しました。これが JavaScript でインスタンス メンバーとメソッドを正しく実装する方法の完全な例を提供し、ここにたどり着いたすべての開発者がさまざまな実装の落とし穴を理解できるようになることを願っています。

次の JavaScript オブジェクトを検討してください。

var MessageBox = (function() {
    function MessageBox(message) {
        this.message = message;
    }

    MessageBox.prototype.Show = function() {
        alert(this.message);
    }
})();

このオブジェクトは TypeScript を使用してモデル化されており、次のように使用できます。

var msg1 = new MessageBox("Hello World");
msg1.Show(); // alerts "Hello World"

var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"

しかし、私はまだ呼び出すことができます:

msg1.message; // "Hello World"
msg2.message; // "Bye World"

だから明らかにthis.messageプライベートではありません。

次に、次の JavaScript オブジェクトについて考えてみましょう。

var MessageBox = (function() {
    return function MessageBox(message) {
        var message = message;

        MessageBox.prototype.Show = function() {
            alert(message);
        }
    }
})();

MessageBoxこれは、TypeScript ベースのオブジェクトの単なる修正版です。

var msg1 = new MessageBox("Hello World");
msg1.Show(); // alerts "Hello World"

var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"

しかし、待ってください...私は作品にスパナを投げようとしています!

var msg1 = new MessageBox("Hello World");
var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"
msg1.Show(); // alerts "Bye World" ... wait, what!?

msg1.message // undefined
msg2.message // undefined

そのため、メッセージ変数にアクセスできなくなりましたが、新しいインスタンスごとに最後のインスタンス メッセージが上書きされます。

これは考慮すべき最後の JavaScript オブジェクトです。

var MessageBox = (function() {
    return function MessageBox(message) {
        var message = message;

        this.Show = function() {
            alert(message);
        }
    }
}();

上記のオブジェクトは、プロトタイプに Show() を実装しなくなったため、次のことができるようになりました。

var msg1 = new MessageBox("Hello World");
var msg2 = new MessageBox("Bye World");
msg2.Show(); // alerts "Bye World"
msg1.Show(); // alerts "Hello World"

msg1.message // undefined
msg2.message // undefined

すごい!これで、プライベート変数ができました。それらは互いに上書きしません!

それで、最後に質問:次の違いは何ですか:

MessageBox.prototype.Show = function() {
}

this.Show = function() {
}
4

2 に答える 2

1

最終的にたどり着く質問には、簡単な答えがあります。プロトタイプに関数を設定すると、どのインスタンスからでも呼び出すことができ、インスタンスに関数を設定すると、そのインスタンスからのみ呼び出すことができるということです。どちらの方法でもインスタンスのプロパティにアクセスできますが、複雑なのは、関数が宣言されたスコープ内またはスコープを含むスコープ内のローカル変数にのみアクセスできることです。

以下は、プライベート インスタンス変数とプライベート プロトタイプ変数の両方を提供するために頭に浮かんだ最初の方法です。

var MessageBox = (function() {
    var privateProtoVar = "Hello";

    function MessageBox(message) {
        var privateInstanceVar = message;

        this.instanceMethod = function() {
            alert(privateInstanceVar); // Can access private instance var
            alert(privateProtoVar);    // Can access private prototype var
        }
    }        
    MessageBox.prototype.Show = function() {
        alert(privateProtoVar); // Can access private proto var
        // but can't access privateInstanceVar
    }    
    return MessageBox;
})();

var msg1 = new MessageBox("1"),
    msg2 = new MessageBox("2");

msg1.instanceMethod();  // "1", "Hello"
msg2.instanceMethod();  // "2", "Hello"
msg1.Show();            // "Hello"
msg2.Show();            // "Hello"

変数は、内部関数内privateInstanceVarで宣言された任意の関数からアクセスできますが、同じスコープ内で宣言されていない限り、上の関数からはアクセスできません (上記の例では行っていません)。MessageBox()prototype

後でインスタンスに追加のメソッドを追加する場合、つまり、上記の構造の外にある場合、それらのメソッドは別のスコープで宣言されているため、プライベート var にアクセスできません。

msg1.newMethod = function() {
   alert(privateInstanceVar);
}
msg1.newMethod(); // error

デモ: http://jsfiddle.net/SSEga/

于 2013-05-22T09:58:48.433 に答える