我已经制作了一个JS对象,它带有一些原型函数,可以使用this。[function]从构造函数中调用它们。

但是在以后的事件处理程序函数中,这是指元素,而不是对象,并且我不确定如何解决此问题:

它通过AddListener正常运行,触发鼠标按下事件,从而使enable / disableDragging正常运行。但是在该函数中,“ this”是元素,而不是拖动器对象,因此我无法调用对WindowCenter,DraggingBool或Add / RemoveListener事件的访问。

通过阅读,看来我可能需要实现prototype.bind?但不确定如何重新排列现有代码以执行此操作。还是我更改其中一个函数以返回一个函数?

是的,我知道我可以在jQuery中做到这一点,做了很多次,只是想看看我是否可以使用POJS实现它:)

Dragger = function(element, draggingElement) {
    this.Element = element;
    this.DraggingElement = element;
    this.WindowCenter;
    this.DraggingBool = false;

    this.AddListener(this.DraggingElement, "mousedown", this.enableDragging);
    this.AddListener(this.DraggingElement, "mouseup", this.disableDragging);
}

Dragger.prototype.AddListener = function (element, eventType, listener, bubble) {
    if (typeof (element) != "object" || typeof (listener) != "function")
        return;
    if (typeof (bubble) == "undefined")
        var bubble = false;
    eventType = eventType.toLowerCase();
    if (eventType.substr(0, 2) == "on")
        eventType = eventType.substr(2);
    if (window.addEventListener) { // Mozilla, Netscape, Firefox
        element.addEventListener(eventType, listener, bubble);
    } else if (window.attachEvent) { // IE
        element.attachEvent("on" + eventType, listener);
    }
}

Dragger.prototype.RemoveListener = function (element, eventType, listener) {
    eventType = eventType.toLowerCase();
    if (eventType.substr(0, 2) == "on")
        eventType = eventType.substr(2);
    if (window.addEventListener) { // Mozilla, Netscape, Firefox
        element.removeEventListener(eventType, listener, false);
    } else if (window.attachEvent) { // IE
        element.detachEvent("on" + eventType, listener);
    }
}

Dragger.prototype.enableDragging = function (e) {
    if (!e) var e = window.event;
    //dont move for right click
    if (e.which && e.which == 3)
        return;
    else if (e.button && e.button == 2)
        return;

    this.DraggingBool = true;
    this.WindowCenter = new Point(e.pageX, e.pageY);
    this.AddListener(document.body, "mouseover", this.mouseMoveListener);
}

Dragger.prototype.disableDragging = function () {
    this.DraggingBool = false;
    this.RemoveListener(document.body, "mouseover", this.mouseMoveListener);
}

Dragger.prototype.mouseMoveListener = function (e) {
    if (!this.DraggingBool)
        return;
    if (!e) var e = window.event;
    e.preventDefault();
    var newLoc = new Point(e.pageX, e.pageY);
    var xDif = windowCenter.X - newLoc.X;
    var yDif = windowCenter.Y - newLoc.Y;
    this.Element.style.left = (this.Element.offsetLeft + xDif) + "px";
    this.Element.style.top = (this.Element.offsetTop + yDif) + "px";
    this.WindowCenter = newLoc;
}

最佳答案

这是因为使用addEventListener时,执行范围设置为节点,就像使用node.onclick = foo一样。在IE中使用attachEvent时,执行范围将成为全局执行范围,即窗口。

解决此问题的一种方法是使用Function.call或Function.apply指定您喜欢的执行范围。许多库都会声明一个绑定函数来帮助实现这一点,例如:

function bind(fn, context) {
  return function() {
    return fn.apply(context, arguments);
  };
}

this.AddListener(this.DraggingElement, "mousedown",
    bind(this.enableDragging, this));


您还可以在AddListener函数中添加上下文参数,并在那里进行绑定。

Ecmascript 5具有内置的bind方法。

09-20 23:47