我试图理解为什么在下面的代码中我需要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;
}
我被告知这是因为this
在没有它的情况下发生了变化,但我不明白为什么this
会发生变化,为什么包裹函数会阻止它发生变化,以及this
会发生什么变化没有包装功能。
答案 0 :(得分:7)
你需要包装它们,因为当一个函数被用作事件处理程序时,this
关键字指的是触发事件的DOM元素,如果你不包装它,你就没有访问Dragger
对象的实例成员,例如this.isMouseDown
。
例如:
假设你有一个按钮:
<input type="button" id="buttonId" value="Click me" />
你有以下对象:
var obj = {
value: 'I am an object member',
method: function () {
alert(this.value);
}
}
如果你打电话:
obj.method();
您会看到value
对象的obj
成员中包含文字的提醒('我是对象成员')。
如果您使用obj.method
函数作为事件处理程序:
document.getElementById('buttonId').onclick = obj.method;
当用户点击该按钮时,它会提醒'点击我'。
为什么呢?
因为当点击事件被触发时,obj.method
将执行,this
关键字指向DOM元素,它将提醒'点击我',因为该按钮包含value
成员。
您可以查看上面运行here的代码段。
对于上下文执行,我始终保持关闭bind函数:
// 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
的对象,其余的可选参数是将在此处调用包装的函数中心代码。
在按钮示例中,我们可以将其用作:
document.getElementById('buttonId').onclick = obj.method.bind(obj);
它在很多情况下都非常有用,它将作为ECMAScript 5的一部分引入。
答案 1 :(得分:3)
CMS gave a good answer关于this
在不同情境中的价值。但是作为旁注,这里有一个方便的函数,如果你没有使用库或使用没有库的库,你可以使用它来概括Dragger.wrap
(类似于dojo.hitch
)的效果。有这样一个工具:
var lockContext = function(context, callback) {
return function() {
callback.apply(context, arguments);
}
};