从原型中的事件访问 "this"

Accessing "this" from event in prototype

考虑以下代码...使用 Hammer.js 但我认为它可能是一个通用的 Javascript 问题:

var drawLayer = new DrawLayer(document.getElementById('canvasContainer'));

function DrawLayer(targetElement) {
    this.foo = "bar";

    this.gestureDetection = new Hammer.Manager(targetElement);
    this.gestureDetection.add(new Hammer.Pan({
            direction : Hammer.DIRECTION_ALL,
            threshold : 0
        }));
    this.gestureDetection.add(new Hammer.Press({
            time : 0,
            threshold : 5
        }));
    this.gestureDetection.on("press", this.drawBegin);
    this.gestureDetection.on("panmove", this.drawMove);
    this.gestureDetection.on("panend pressup", this.drawEnd);

    this.drawBegin("INIT TEST");
}

DrawLayer.prototype.drawBegin = function (gestureData) {
    console.log(typeof(this.foo));
    console.log("DRAW BEGIN!");
}

DrawLayer.prototype.drawMove = function (gestureData) {
    console.log(this.foo);
    console.log("DRAW MOVE!");
}

DrawLayer.prototype.drawEnd = function (gestureData) {
    console.log(this.foo);
    console.log("DRAW END!");
}

当我第一次运行它时,我得到了预期的结果:

string
DRAW BEGIN!

但是当实际处理手势时(即当通过事件调用绘图时),我得到:

undefined
DRAW BEGIN!

更多关于这一点 - 似乎在处理任何这些 drawBegin/etc 时。方法,"this" 未定义,好像它不知何故失去了范围?

我想要一个解决方案和一个解释。谢谢!

"this" 的值取决于调用函数的方式。

在第一种情况下,您直接从 DrawLayer 调用 drawBegin 函数 class:

this.drawBegin("INIT TEST");

在这种情况下,此变量表示 DrawLayer 对象。

当您通过事件调用函数时

this.gestureDetection.on("press", this.drawBegin);

"this" 变量可以被函数包装 "on" 以表示其他任何东西(通常是事件本身或触发事件的对象)。

尝试将您的代码更改为以下内容,看看是否有效:

function DrawLayer(targetElement) {
    this.foo = "bar";

    this.gestureDetection = new Hammer.Manager(targetElement);
    this.gestureDetection.add(new Hammer.Pan({
            direction : Hammer.DIRECTION_ALL,
            threshold : 0
    }));
    this.gestureDetection.add(new Hammer.Press({
            time : 0,
            threshold : 5
    }));
    this.gestureDetection.on("press", this.drawBeginWrapper);
    this.gestureDetection.on("panmove", this.drawMove);
    this.gestureDetection.on("panend pressup", this.drawEnd);

    var _self = this;

    this.drawBeginWrapper = function(gestureData) {
          _self.drawBegin(gestureData);
    } 

    this.drawBegin("INIT TEST");
}

您可以像这样将 "this" 绑定到事件回调:

this.gestureDetection.on("press", this.drawBegin.bind(this));

当回调被事件触发时,应该有正确的"this"。