【问题标题】:Unable to resolve Javascript object method this reference无法解析 Javascript 对象方法此引用
【发布时间】:2010-06-25 10:22:20
【问题描述】:

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

但在后面的事件处理函数中,this指的是元素,而不是对象,我不知道如何解决这个问题:

它通过 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;
}

【问题讨论】:

    标签: javascript oop function-prototypes


    【解决方案1】:

    这是因为在使用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 有一个内置的绑定方法。

    【讨论】:

    • 太棒了!干杯,比我在创建对象实例时将全局变量设置为对象实例并在函数中调用它的技巧要好得多:) 现在我必须让它在 IE 中工作,因为你显然无法设置样式.left ¬.¬.但我会弄清楚的^^
    【解决方案2】:
      Function.prototype.bind = function () {
        if (arguments.length < 2 && arguments[0] === undefined) {
         return this;
       }
    
        var thisObj = this,
        args = Array.prototype.slice.call(arguments),
    
        obj = args.shift();
    
        return function () {
         return thisObj.apply(obj, args.concat(Array.prototype.slice.call(arguments)));
        };
    
      };
    
    
    
      Function.bind = function() {
        var args = Array.prototype.slice.call(arguments);
        return Function.prototype.bind.apply(args.shift(), args);
    
      }
    
    Dragger = function(element, draggingElement) {
        this.Element = element;
        this.DraggingElement = element;
        this.WindowCenter;
        this.DraggingBool = false;
    
        this.AddListener(this.DraggingElement, "mousedown", this.enableDragging,this); 
        this.AddListener(this.DraggingElement, "mouseup", this.disableDragging,this);
    }
    
    Dragger.prototype.AddListener = function (element, eventType, listener, bubble,dragger_obj) {
        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.bind(dragger_obj), bubble);
        } else if (window.attachEvent) { // IE
            element.attachEvent("on" + eventType, listener.bind(dragger_obj));
        }
    }
    
    Dragger.prototype.RemoveListener = function (element, eventType, listener,dragger_obj) {
        eventType = eventType.toLowerCase();
        if (eventType.substr(0, 2) == "on")
            eventType = eventType.substr(2);
        if (window.addEventListener) { // Mozilla, Netscape, Firefox
            element.removeEventListener(eventType, listener.bind(dragger_obj), false);
        } else if (window.attachEvent) { // IE
            element.detachEvent("on" + eventType, listener.bind(dragger_obj));
        }
    }
    
    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,this);
    }
    
    Dragger.prototype.disableDragging = function () {
        this.DraggingBool = false;
        this.RemoveListener(document.body, "mouseover", this.mouseMoveListener,this);
    }
    
    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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-21
      • 2013-02-04
      • 2021-04-23
      • 1970-01-01
      • 2014-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多