从原型中的事件访问“this”

Accessing "this" from event in prototype

本文关键字:this 访问 事件 原型      更新时间:2023-09-26

请考虑以下代码...使用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"绑定到事件回调,如下所示:

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

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

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

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

this.drawBegin("INIT TEST");

在这种情况下,此变量表示绘图层对象。

通过事件调用函数时

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");
}