8

サイトをディープリンクするためにSWFAddressを使用しています(SWFAddressへのリンク)。私はコードをクラスに分割するのが好きなので、次のようなメイン構造になっています。

function SomeClass() {
    // This adds the this.handleChange() function to the
    // SWFAddress event listener
    this.initializeSWFA = function() {
        // SWFAddress variable is instantiated in SWFAddress javascript file
        // so I can use it here
        SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);
    }

    // SWFAddress is supposed to call this function
    this.handleChange = function(evt) {
    // Some code here
    }

}

// Instantiate the SomeClass
var someVar = new SomeClass();
someVar.initializeSWFA();

この行はここでは機能しません:

SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);

私はそれを次のように変更してみました:

SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange());

また

var self = this;
SWFAddress.addEventListener(SWFAddressEvent.CHANGE, self.handleChange);

そして、これらも機能しません。

では、このような状況でクラスからJavaScript関数を参照するにはどうすればよいですか?

関数handleChangeがクラスの外にある場合は、関数の名前を書くことができます。


まず、すべての回答ありがとうございます。私はまだこれがJavaScriptでどのように機能するかを理解しようとしています。私はここJavaScriptのようなオブジェクト指向モデルには慣れていません。

これが今のところ解決策です。JavaScriptでこれをうまく行う方法をまだ理解できませんが、このソリューションは機能します。ehudokai(ありがとう)が提案した解決策を実装しようとしましたが、うまくいきませんでした。

function SomeClass() {
    // This adds the this.handleChange() function to the
    // SWFAddress event listener
    this.initializeSWFA = function() {
        // SWFAddress variable is instantiated in SWFAddress javascript file
        // so I can use it here
        SWFAddress.addEventListener(SWFAddressEvent.CHANGE, someFunc);
    }

    // SWFAddress suppose to call this function
    this.handleChange= function(evt) {
    // Some code here
    }

}

// Instantiate the SomeClass
var someVar = new SomeClass();

function someFunc(evt) {
    someVar.handleChange(evt);
}

someVar.initializeSWFA();

これには1つの追加関数の定義が含まれるため、これは好きではありません。JavaScriptオブジェクトからSWFAddress EventListenerにメソッドを追加する方法を誰かが理解すると、余分なスペースが必要になります。私を助けてください。

4

3 に答える 3

12

クラス構造は完全に有効です。ただし、handleChange()関数がthisキーワードを使用している場合は、期待してsomeVar、それが問題の原因です。

これが起こることです:

  1. SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);クラス内のハンドラー関数を正しく参照します。SWFAddressfは、イベントがディスパッチされるまで、その関数をいくつかの変数にキャッシュします。
  2. イベントがディスパッチされると、SWFAddressはを呼び出しますf。関数への参照は保持されますが、コンテキストへの参照、またはは保持されthisません。したがってthis、デフォルトはwindow

これを回避するには、クラススコープ内の変数をキャプチャする無名関数を使用する必要があります。この無名関数内から正しいコンテキストでハンドラーを呼び出すことができます。

function SomeClass() {
    this.initializeSWFA = function() {
        // Save a reference to the object here
        var me = this;

        // Wrap handler in anonymous function
        SWFAddress.addEventListener(SWFAddressEvent.CHANGE, function (evt) {
            me.handleChange(evt);
        });
    }

    // SWFAddress suppose to call this function
    this.handleChange= function(evt) {
    // Some code here
    }

}

this## OPからの要求に応じた、の説明:##

thisキーワードはさまざまな方法で説明できます。最初にスコープに関するこの記事を読み、次にオブジェクト指向JavaScriptに関するこの記事を読んでください。

私も私の簡単な推論を投げ入れたいと思います、それはあなたが役に立つと思うかもしれません。JavaScriptには、Javaなどの言語のような「クラス」がないことに注意してください。これらの言語では、クラスの「メソッド」はそのクラスにのみ属します(または継承される可能性があります)。ただし、JavaScriptには、関数に発生する可能性のあるオブジェクトとオブジェクトプロパティのみがあります。これらの関数はフリーエージェントです。文字列や数字のように、あるオブジェクトや別のオブジェクトに属していません。例えば:

var a = {
    myMethod: function () {...}
};

var b = {};
b.myMethod = a.myMethod;

この場合、どのオブジェクトがmyMethod属しますか?答えはありません。またはのいずれabです。したがって、これa.myMethodは単に「コンテキスト」または親オブジェクトから関連付けられていない関数への参照です。したがって、またはを使用して明示的に呼び出されthisない限り意味がなく、他の方法で呼び出された場合はデフォルトになります。JavaScriptにaやキーワードなどがないのも同じ理由です。a.myMethod()b.myMethod()windowparentsuper

于 2011-01-04T07:39:23.827 に答える
2

最善の方法は、SomeClassをクラスとして考えるのをやめることだと思います。

JavaScriptにはクラスがありません。プロトタイプの継承を使用します。ここにはあまり深く入りません。基本的に、それはあなたがただオブジェクトを持っていることを意味します。また、最初のオブジェクトのような別のオブジェクトを作成する場合は、Object.prototype属性を使用して作成します。

したがって、(SWFAddressがほとんどのJavaScriptのように機能すると仮定して)実行しようとしていることを実行したい場合は、次のようにします。

var someVar = {  // (Using object notation)
    initializeSWFA : function(){
        SWFAddress.addEventListener(SWFAddressEvent.CHANG, this.handleChange);
    },
    handleChange : function(){
        // Your code here
    }
}

この時点で、someVarを直接呼び出すことができます。

someVar.initializeSWFA();

代わりに、他のオブジェクトを継承できるオブジェクトを作成する場合は、次のことを試してください。

var baseObject = function(){};
baseObject.prototype.handleChange = function(){
    // Your code here
}
baseObject.prototype.initializeSWFA = function(){
    SWFAddress.addEventListener(SWFAddressEvent.CHANGE, this.handleChange);
}

var someVar = new baseObject();
someVar.initializeSWFA();

new演算子は、指定されたオブジェクトの.prototypeを継承する新しいオブジェクトを作成するだけです。

于 2011-01-03T17:57:36.760 に答える
1

私はあなたの問題を特定することはできませんが、それはあなたの使用と関係があると思いますSWFAddressSomeClassここで他のいくつかの答えが述べていることに反して、あなたが構築している方法とその方法は完全に有効です。

どのように機能するかに関する、別の回答からのmikiの(現在は削除されている)質問のさらなる明確化this

this動作には2つのケースがあります。通常の関数とnew-operatorで呼び出される関数。

通常の関数呼び出しの場合this、はドットの左側にあるオブジェクトを参照します(大まかに言えば)。たとえば、を書くときはsomeVar.initializeSWFA()thisを参照しsomeVarます。ドットなしで関数を呼び出す場合、thisはグローバルオブジェクトを参照します。関数は、あるオブジェクトから別のオブジェクトに割り当てることができるためthis、次のようにシフトされます。

var someVar = new SomeClass();
var anotherVar = {};
anotherVar.aNewNameForTheSameFunction = someVar.initializeSWFA;
anotherVar.aNewNameForTheSameFunction(); // Inside of this call to initializeSWFA, "this" will be "anotherVar"

new次に、 -operatorを使用して呼び出された場合もあります。その場合、newは新しいオブジェクトを作成し、thisそのオブジェクトを参照します。

-functionthisを使用して、明示的に設定された関数を呼び出す方法もあります。call

var someVar = new SomeClass();
var aNumber = 5;
someVar.initializeSWFA.call(aNumber, arg1, arg2, ..., argN);

aNumberこれにより、 asを使用して関数initializeSWFAが呼び出され、パラメーター、などthisが渡されます。この場合、方程式から除外されていることに注意してください。arg1arg2someVar

于 2011-01-03T17:20:32.263 に答える