3

このことはほとんど機能します:

function myClass(url) {

this.source = url;
this.rq = null;
this.someOtherProperty = "hello";

// open connection to the ajax server
this.start = function() {
    if (window.XMLHttpRequest) {
        this.rq = new XMLHttpRequest();
        if (this.rq.overrideMimeType)
        this.rq.overrideMimeType("text/xml"); 
    } else
        this.rq = new ActiveXObject("Microsoft.XMLHTTP");

    try {
        this.rq.onreadystatechange = connectionEvent;
        this.rq.open("GET", this.source, true);
        this.rq.send(null);
        this.state = 1;
    } catch (err) {
        // some error handler here
    }

}

function connectionEvent() {
    alert("i'm here");
    alert("this doesnt work: " + this.someOtherProperty);
}

} // 私のクラス

つまり、XMLHttpRequestオブジェクトをグローバルに定義するのではなく、クラスのメンバーとして持ち、従来の方法で呼び出すことに他なりません。ただし、connectionEventコールバック関数内では、関数自体がmyClass内でスコープされていても、「this」の意味は失われます。また、myClassからインスタンス化するオブジェクトが十分に長く存続していることを確認しました(スクリプトでグローバルに宣言されています)。

私が見たjavascriptクラスの使用例ではすべて、「this」は内部関数内で引き続き使用可能でした。私にとっては、関数を外部に持ち出してmyClass.prototype.connectionEventにしたとしても、そうではありません。私は何が間違っているのですか?ありがとうございました。

4

1 に答える 1

6

それが機能しない理由は、Javascriptではthis、関数が定義されている場所ではなく、関数が呼び出される方法によって完全に定義されているためです。これは他のいくつかの言語とは異なります。

あなたthisが期待することを意味するためには、それを「バインド」することによって明示的にそれを確実にする必要があります:

this.start = function() {
    var self = this; // Set up something that survives into the closure

    /* ...lots of stuff omitted... */

    this.rq.onreadystatechange = function() {
        // Call `connectionEvent`, setting `self` as `this` within the call
        connnectionEvent.call(self);
    };

このブログ投稿thisには管理に関する詳細情報がありますが、基本的には、特別な努力をせずに関数を呼び出すと、関数内は常にグローバルオブジェクト(ブラウザーでは)になります。電話をかけるときに設定する方法は2つあります。thisthiswindowthis

  1. 上記のようにFunction#call(または)を使用して、最初のパラメーターとしてFunction#apply使用するオブジェクト参照を渡します。thisこれは関数を呼び出し、渡したものに設定します。とthisの違いは、関数に渡す引数をさらに指定する方法です。あなたがそれらを呼び出しへのさらなる引数として提供する場合(例えば)、あなたがそれらを2番目の引数()の配列として提供する場合。#call#apply#call#callfunc.call(thisArg, arg0, arg1, arg2)#applyfunc.apply(thisArg, [arg0, arg1, arg2])
  2. ドット表記の使用:関数が割り当てられたプロパティ(startプロパティなど)を持つオブジェクトがある場合、オブジェクトインスタンス、ドット、およびプロパティ名(this.start()またはfoo.start()など)を使用してオブジェクトを呼び出すと、関数が呼び出されます。this呼び出し内のオブジェクトインスタンスに設定します。したがって、ドット付き表記は2つのまったく異なることを行います。プロパティを検索し、その値として関数を見つけ、this呼び出し中にオブジェクトに設定されるような関数を呼び出します。文字通りそれは次のようなものです:var f = obj.func; f.call(obj)

少し話題から外れていますが、本当に正当な理由がなければ、私はこのホイールを再発明しません。単純にXHR呼び出しを行うためのライブラリはたくさんあります。jQueryPrototypeClosure、およびその他のほぼすべて。

于 2010-05-14T18:08:14.090 に答える