0

我会将我以前的 js 代码移动到更多的 OOP 风格。这是代码。

function addEvent( obj, type, fn ) {
  if ( obj.attachEvent ) {
    obj['e'+type+fn] = fn;
    obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
    obj.attachEvent( 'on'+type, obj[type+fn] );
  } else
    obj.addEventListener( type, fn, false );
}

function test() {

}

test.prototype = {
    init: function () {

        addEvent(document, 'mousedown', this.displaydown);

    },

    displaydown : function(e){
        document.getElementById('mydiv').innerHTML = "down";
        addEvent(document, 'mousemove', this.displaymove);
    },

    displaymove : function(e){
        document.getElementById('mydiv').innerHTML = "move";
    }
}

var test0 = new test();

test0.init()

mousedown 后我无法添加 mousemove 事件

addEvent(document, 'mousemove', this.displaymove);

但是如果我写像这样的内联样式

addEvent(document, 'mousemove', function(e){
   document.getElementById('mydiv').innerHTML = "move";
});

没关系。看起来这两个代码做同样的事情。为什么有区别?谢谢!


编辑,

经过2个晚上的努力,我终于解决了这个问题。感谢约翰维的启发。

关键字出现错误。如果是对象,this 指的是窗口而不是对象本身。解决方案是我在开始时定义了全局参数me (me = this)。现在好啦。

4

1 回答 1

2

这是一个经典的 Javascript 绊脚石,与“this”键在闭包中的作用域有关。为了显示:

redPrinter = function() {
    this.X = 'red';
    return function() {
        return this.X;
    }
}

main = function() {
    this.X = 'blue';
    var myRedPrinter = new redPrinter();
    alert("Red printer returned: " + myRedPrinter());
}

main();

此代码将打印出来:

Red printer returned: blue

因为“this”在该行中的范围:

return this.X

实际上在调用时与 main() 对象相关联。

通常有两种方法可以解决这个问题:

1) 避免在函数闭包中使用 'this' 关键字。要以这种方式修复您的代码,我只需将所有事件绑定收集在一个地方而不是级联它们,从而从“displaydown()”和“displaymove()”中删除“this”引用:

test.prototype = {
    init: function () {
        addEvent(document, 'mousedown', this.displaydown);
        addEvent(document, 'mousemove', this.displaymove);
    },

    displaydown : function(e){
        document.getElementById('mydiv').innerHTML = "down";
    },

    displaymove : function(e){
        document.getElementById('mydiv').innerHTML = "move";
    }
}

或者

2) 使用函数currying在定义时绑定范围。我从 Prototype 库中提取了 bind() 方法来说明:

// declare the global bind() method for all functions
Function.prototype.bind = function(obj) {
    var method = this,
    temp = function() {
        return method.apply(obj, arguments);
    };
    return temp;
} 

test.prototype = {
    init: function () {
        addEvent(document, 'mousedown', this.displaydown);
    },

    displaydown : function(e){
        document.getElementById('mydiv').innerHTML = "down";

        // note that we bind the method object here
        addEvent(document, 'mousemove', this.displaymove.bind(this));
    },

    displaymove : function(e){
        document.getElementById('mydiv').innerHTML = "move";
    }
}

这里的重要变化是:

this.displaymove.bind(this)

它基本上说,“当您调用 displaymove() 时,将关键字 'this' 重新范围为原始范围上下文而不是当前的 Event 对象。

于 2009-05-05T05:14:45.300 回答