其他答案没有解释发生了什么,因此给出了不正确的建议。
JavaScript 具有一流的函数对象——您可以将它们作为值传递。这正是您设置此回调时所做的事情:
this.preview.addEventListener('click', this.click, false);
您正在获取 this.click 属性的内容,它恰好是一个函数,并将其交给 addEventListener 函数来做任何它想做的事情。
我对那里的术语非常具体-注意我专门说的是功能,而不是方法。JavaScript 并没有真正的方法构造,它只是将方法作为对象的属性。
那么“this”成员是从哪里来的呢?这是在调用者处确定的 - 您在“。”左侧使用的对象。是成为这个价值的那个。例如,
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"
通过两个不同的对象调用的完全相同的函数对象具有不同的 this 指针。
exampleFunc 是一个全局函数,我们称之为:
exampleFunc() // Outputs "this.myName = undefined"
那么 undefined 是从哪里来的呢?在全局函数中,“this”设置为 window(全局范围),它没有定义 myName 属性。这也意味着您可以这样做:
myName = "Global Name"; // note, no var - we want this global
exampleFunc(); // Outputs "this.myName = Global Name"
好的,那么原始问题是怎么回事?基本上,您已将函数 this.click 传递为回调函数,但尚未传递希望调用它的“this”指针。实际上, addEventListener 没有办法传递 this 指针。结果,当调用函数时, this并不指向您的对象。我不记得它指的是什么 - 它是窗口或被点击的元素,请查看 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”有很多不同的值。跟踪“this”指向的内容是掌握 JavaScript 编程的重要部分。