他の答えは何が起こっているのかを説明しておらず、そのため間違ったアドバイスをしています。
JavaScriptにはファーストクラスの関数オブジェクトがあります-それらを値として渡すことができます。これは、このコールバックを設定するときに行っていることとまったく同じです。
this.preview.addEventListener('click', this.click, false);
たまたま関数であるthis.clickプロパティの内容を取得し、それをaddEventListener関数に渡して、必要な処理を実行します。
私はそこでの用語について非常に具体的でした-私が具体的に言ったのはメソッドではなく関数であることに注意してください。JavaScriptには実際にはメソッド構造がなく、オブジェクトのプロパティとしてメソッドがあるだけです。
では、「この」メンバーはどこから来たのでしょうか。これは、呼び出し元(「。」の左側で使用するオブジェクト)で決定されます。これの値になるものです。例えば、
function exampleFunc() { console.log("this.myName = " + this.myName); }
var a = { myName: "Chris", doSomething: exampleFunc };
var b = { myName: "Bob", doSomething: exampleFunc };
doSomethingプロパティにまったく同じ関数を割り当てたことに注意してください。何が起こるか:
a.doSomething(); // Outputs "this.myName = Chris"
b.doSomething(); // Outputs "this.myName = Bob"
2つの異なるオブジェクトを介して呼び出されるまったく同じ関数オブジェクトには、異なるthisポインターがあります。
exampleFuncはグローバル関数です。それを呼び出しましょう:
exampleFunc() // Outputs "this.myName = undefined"
では、未定義はどこから来たのでしょうか?グローバル関数では、「this」はmyNameプロパティが定義されていないwindow(グローバルスコープ)に設定されます。これは、代わりにこれを実行できることも意味します。
myName = "Global Name"; // note, no var - we want this global
exampleFunc(); // Outputs "this.myName = Global Name"
では、元の質問はどうなっているのでしょうか。基本的に、コールバックとなる関数this.clickを渡しましたが、呼び出したい「this」ポインターを渡していません。実際、addEventListenerには、このポインターを渡す方法がありません。その結果、関数が呼び出されたとき、これはオブジェクトを指していません。頭のてっぺんから何を指しているのか覚えていません。ウィンドウまたはクリックされた要素のいずれかです。DOMのドキュメントを確認してください。
適切なコンテキスト(コンテキスト=正しい「this」)で適切な関数を呼び出すための従来のアプローチは、クロージャを使用することです。「this」を変数にキャプチャしてから、右のthisポインタを使用して実際のコールバックを呼び出す無名関数を渡します。コードは次のようになります。
var preview = WinJS.Class.define(
function (el, options) {
// Capture your current this pointer in a global variable
// Using "that" as the name comes from JavaScript: The Good Parts book
var that = this;
el.winControl = this;
this.el = el;
this.textarea = d.getElementById('preview-input');
this.preview = d.getElementById('preview-text');
this.form = d.getElementById('perview-form');
// Note what gets passed instead of this.click:
this.preview.addEventListener('click',
function (e) {
// NOTE: Calling through "that": "this" isn't pointing to the right object anymore
// Calling through "that" resets "this" inside the call to click
that.click(e);
}, false);
},
{
click: function (e) {
this.form.style('display', 'block');
}
}
);
これは、ECMAScript 5にこれらのラッパーを作成するためのユーティリティ関数(function.bind)があるのに十分な一般的なパターンです。これを行う:
this.preview.addEventListener('click',
this.click.bind(this),
false);
コンストラクトthis.click.bind(this)
は、呼び出されると、渡したもの(この場合は「this」)に「this」参照を設定する新しい関数を作成し、呼び出した関数を呼び出します。
はい、「this」にはさまざまな値が浮かんでいます。「これ」が何を指しているのかを追跡することは、JavaScriptプログラミングを習得する上で重要な部分です。