(javascript)为什么我需要为事件处理程序使用wrap函数?

(javascript)为什么我需要为事件处理程序使用wrap函数?,javascript,closures,event-handling,wrap-function,Javascript,Closures,Event Handling,Wrap Function,我试图理解为什么在下面的代码中我需要Dragger.prototype.wrap,以及为什么我不能直接使用事件处理方法: function Dragger(id) { this.isMouseDown = false; this.element = document.getElementById(id); this.element.onmousedown = this.wrap(this, "mouseDown"); } Dragger.prototype.wrap =

我试图理解为什么在下面的代码中我需要Dragger.prototype.wrap,以及为什么我不能直接使用事件处理方法:

function Dragger(id) {
    this.isMouseDown = false;
    this.element = document.getElementById(id);
    this.element.onmousedown = this.wrap(this, "mouseDown");
}

Dragger.prototype.wrap = function(obj, method) {
    return function(event) {
        obj[method](event);
    }
}

Dragger.prototype.mouseDown = function(event) {
    this.oldMoveHandler = document.body.onmousemove;
    document.onmousemove = this.wrap(this, "mouseMove");
    this.oldUpHandler = document.body.onmousemove;
    document.onmouseup = this.wrap(this, "mouseUp");
    this.oldX = event.clientX;
    this.oldY = event.clientY;
    this.isMouseDown = true;
}

Dragger.prototype.mouseMove = function(event) {
    if (!this.isMouseDown) {
        return;
    }
    this.element.style.left = (this.element.offsetLeft
            + (event.clientX - this.oldX)) + "px";
    this.element.style.top = (this.element.offsetTop
            + (event.clientY - this.oldY)) + "px";
    this.oldX = event.clientX;
    this.oldY = event.clientY;
}

Dragger.prototype.mouseUp = function(event) {
    this.isMouseDown = false;
    document.onmousemove = this.oldMoveHandler;
    document.onmouseup = this.oldUpHandler;
}

有人告诉我这是因为
这个
没有它会改变,但我不明白为什么
这个
会改变,为什么wrap函数会阻止它改变,以及没有wrap函数这个会变成什么。

你需要包装它们,因为当函数被用作事件处理程序时,
this
关键字引用触发事件的DOM元素,如果不包装它,则无法访问
Dragger
对象的实例成员,如
this.isMouseDown

例如:

假设您有一个按钮:

<input type="button" id="buttonId" value="Click me" />
如果你打电话:

obj.method();
您将看到一个警报,其文本包含在
obj
对象(“我是对象成员”)的
value
成员中

如果将
obj.method
函数用作事件处理程序:

document.getElementById('buttonId').onclick = obj.method;
当用户单击该按钮时,它将提示“单击我”

为什么?? 因为当触发click事件时,
obj.method
将在
this
关键字指向DOM元素的情况下执行,并且它将发出“click me”警报,因为该按钮包含一个
成员

您可以检查上面运行的代码段


对于上下文强制,我总是关闭一个函数:

// The .bind method from Prototype.js
if (!Function.prototype.bind) {
  Function.prototype.bind = function(){
    var fn = this, args = Array.prototype.slice.call(arguments),
             object = args.shift();
    return function(){
      return fn.apply(object,
        args.concat(Array.prototype.slice.call(arguments)));
    };
  };
}
它允许您包装任何函数,强制执行上下文。作为第一个参数,它接收将用作
this
的对象,其余可选参数是包装函数enter code在此调用的参数

在按钮示例中,我们可以将其用作:

document.getElementById('buttonId').onclick = obj.method.bind(obj);
它在很多情况下都非常有用,它将作为ECMAScript 5的一部分介绍。

关于
在不同上下文中的值。但作为旁注,如果您不使用库或使用没有此类工具的库,您可以使用以下一个方便的函数来概括
Dragger.wrap
(类似于
dojo.hitch
)的效果:

var lockContext = function(context, callback) {
    return function() {
        callback.apply(context, arguments);
    }
};

对不起,你能详细说明一下吗?我不明白。啊,所以区别在于“this”将引用DOM对象本身,而不是处理程序(因此我无法访问类似的内容。isMouseDown,因为a没有isMouseDown,但我的类Dragger有?@hatorade:没错,你明白了。正是因为闭包,对象中声明的方法才得到了对象“this”,因为它保留了生成它的环境?我认为看到对象文字而不是实例化对象可能会让人困惑。你的标题暗示了一个与问题内容不同的问题。您想知道关于事件处理程序、给定范围内的
this
的值,还是
prototype
的类定义?
var lockContext = function(context, callback) {
    return function() {
        callback.apply(context, arguments);
    }
};