Ton*_*ark 3 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 = 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;
}
Run Code Online (Sandbox Code Playgroud)
我被告知这是因为this
没有它的更改,但我不明白为什么this
更改,为什么wrap函数阻止它更改,以及this
如果没有wrap函数会改变什么.
你需要包装它们,因为当一个函数被用作事件处理程序时,this
关键字引用触发事件的DOM元素,如果你不包装它,你就无法访问Dragger
对象的实例成员就像this.isMouseDown
.
例如:
假设您有一个按钮:
<input type="button" id="buttonId" value="Click me" />
Run Code Online (Sandbox Code Playgroud)
你有以下对象:
var obj = {
value: 'I am an object member',
method: function () {
alert(this.value);
}
}
Run Code Online (Sandbox Code Playgroud)
如果你打电话:
obj.method();
Run Code Online (Sandbox Code Playgroud)
您将看到包含在对象value
成员中的文本的警报obj
("我是对象成员").
如果您将该obj.method
函数用作事件处理程序:
document.getElementById('buttonId').onclick = obj.method;
Run Code Online (Sandbox Code Playgroud)
当用户点击按钮时,它会提示"点击我".
为什么?因为当触发click事件时,obj.method
将使用this
指向DOM元素的关键字执行,并且它将提示"Click me",因为该按钮包含一个value
成员.
您可以检查上面的片断跑这里.
对于上下文实施,我总是保持关闭绑定功能:
// 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)));
};
};
}
Run Code Online (Sandbox Code Playgroud)
它允许您包装任何函数,强制执行上下文.作为第一个参数,它接收将被用作的对象,this
其余的可选参数是这里将调用的包装函数中心代码.
在按钮示例中,我们可以将其用作:
document.getElementById('buttonId').onclick = obj.method.bind(obj);
Run Code Online (Sandbox Code Playgroud)
它在很多情况下都非常有用,它将作为ECMAScript 5的一部分引入.
归档时间: |
|
查看次数: |
1974 次 |
最近记录: |