1

私はJavascriptが初めてで、オブジェクトの関数を定義するためのプロパティキーワードを発見しました。オブジェクトを使用して websocket の実験をリファクタリングしようとしましたが、うまくいきません。

これは機能します(オブジェクトなし):

var ws = new WebSocket(something, somethingelse);
ws.onopen = function() {
   ws.send("hello");
   console.log("works");
}

しかし、これはしません:

function MyObject() {
   this.ws = new WebSocket(something, somethingelse);
   this.ws.onopen = this.onOpen;
}

MyObject.prototype.onOpen = function() {
    this.ws.send("hello");   // undefined!
};

ws が定義されていないのはなぜですか? onOpen 関数の割り当てが間違っていますか?

4

1 に答える 1

6

関数を正しく割り当てています (関数を割り当てる方法は 1 つしかありません)。問題は、関数のコンテキストが変化することです。

次の行を検討してください。

this.ws.onopen = this.onOpen;

可能性 1:

ここで、 の内部 WebSocketで、この関数が開始接続への応答として呼び出される場所 (イベント ハンドラーなど) を想定しています。おそらく次のようになります。

this.onopen();

this関数内で何を参照するかは、実行時に関数がどのように呼び出されるかによって決まります(<-このリンクを読んでください。非常に役立ちます)。定義時にバインドされません。あなたの場合、インスタンスthisを参照しWebSocketます。

したがって、この方法で呼び出された場合、 insideは、MyObject.prototype.onOpenインスタンスではなく、プロパティを持たないインスタンスをthis参照します。this.wsWebSocketwsMyObject

これは、次の 2 つの方法で解決できます。

  1. thisをすでに参照しているため、次のように直接this.ws呼び出すことができます。sendthis

    MyObject.prototype.onOpen = function() {
        this.send("hello");
    };
    
  2. this内部MyObject.prototype.onOpenで常にインスタンスを参照したい場合は、MyObjectインスタンスへの明示的な参照を保持する必要があります (例: クロージャ):

    var self = this;
    this.ws.onopen = function() {
        self.onOpen();
    };
    

    onOpenでは、コンストラクターで設定したのと同じように、プロパティを持つインスタンスをthis参照します。MyObjectws

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

おそらく同様に機能します。

于 2012-04-16T14:22:53.757 に答える