Почему я не смог добавить событие mousemove после mousedown в прототипе? - PullRequest
0 голосов
/ 05 мая 2009

Я бы переместил свои прежние js-коды в стиль ООП. Вот код.

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()

Я не могу добавить событие mousemove после mousedown с

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

Но если я напишу встроенный стиль как

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

Все нормально. Похоже, 2 кода делают то же самое. Почему есть разница? Спасибо!


редактировать

После двухдневной борьбы я наконец решил проблему. Спасибо Джонви за твою просветленность.

Ошибка возникает по этому ключевому слову . В случае объекта это относится к окну, а не к самому объекту. Решением является то, что я определил глобальный параметр me (me = this) в начале. Теперь все в порядке.

1 Ответ

2 голосов
/ 05 мая 2009

Это классический камень преткновения в 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 в закрытии функции. Чтобы исправить ваш код таким образом, я бы просто собрал все привязки событий в одном месте, а не каскадировал их, удалив ссылки «this» из обоих «displaydown ()» и «displaymove ()»:

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";
    }
}

OR

2) Используйте функцию curry для привязки области во время определения. Я поднял метод bind () из библиотеки Prototype, чтобы проиллюстрировать:

// 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.

...