関数を正しく割り当てています (関数を割り当てる方法は 1 つしかありません)。問題は、関数のコンテキストが変化することです。
次の行を検討してください。
this.ws.onopen = this.onOpen;
可能性 1:
ここで、 の内部 WebSocket
で、この関数が開始接続への応答として呼び出される場所 (イベント ハンドラーなど) を想定しています。おそらく次のようになります。
this.onopen();
this
関数内で何を参照するかは、実行時に関数がどのように呼び出されるかによって決まります(<-
このリンクを読んでください。非常に役立ちます)。定義時にバインドされません。あなたの場合、インスタンスthis
を参照しWebSocket
ます。
したがって、この方法で呼び出された場合、 insideは、MyObject.prototype.onOpen
インスタンスではなく、プロパティを持たないインスタンスをthis
参照します。this.ws
WebSocket
ws
MyObject
これは、次の 2 つの方法で解決できます。
this
をすでに参照しているため、次のように直接this.ws
呼び出すことができます。send
this
MyObject.prototype.onOpen = function() {
this.send("hello");
};
this
内部MyObject.prototype.onOpen
で常にインスタンスを参照したい場合は、MyObject
インスタンスへの明示的な参照を保持する必要があります (例: クロージャ):
var self = this;
this.ws.onopen = function() {
self.onOpen();
};
内onOpen
では、コンストラクターで設定したのと同じように、プロパティを持つインスタンスをthis
参照します。MyObject
ws
ECMAScript 5 をサポートするブラウザーでは、関数には既にこの手法のメソッドがあり、次のように呼ばれ.bind()
ます。
this.ws.onopen = this.onOpen.bind(this);
可能性 2:
また、次のようにWebSocket
呼び出すこともできます。onopen
this.onopen.call(null);
その場合、コードが厳密モードで実行されるかどうかに応じて、this
を参照するwindow
か、 になります (問題ではなく、いずれにせよ問題になります)。undefined
この状況は、最初の可能性からの 2 番目の解決策でのみ解決できます。
最初の例が機能するのはなぜですか?
var ws = new WebSocket(something, somethingelse);
ws.onopen = function() {
ws.send("hello");
console.log("works");
}
この場合、割り当てる関数ws.onopen
はクロージャーであり、このスコープで定義された変数も閉じますws
。この意味では、問題を解決する 2 番目の方法に似ていますが、
ws.onopen = function() {
this.send("hello");
console.log("works");
}
おそらく同様に機能します。