Контекст выполнения Javascript, контр-интуитивно понятная цепочка областей действия внутри обработчиков мыши - PullRequest
2 голосов
/ 12 февраля 2011

Вот интересный случай цепочки областей действия, не описанный во многих документах, который мне трудно понять.Если кто-то может найти время, чтобы прочитать хорошо прокомментированный код ниже и объяснить, как переменная разрешается, было бы очень хорошо

У меня есть два прямоугольника (DIV) на документе.Я регистрирую прослушиватели событий для mousedown на обоих, а внутри прослушивателя mousedown я регистрирую mouseup.Странная вещь происходит в слушателе mouseup.

Два контекста выполнения создаются путем двойного вызова testfunc с разными значениями аргументов:

window.onload = function() {
     test_func("horizontal"); // First Execution context
     test_func("vertical");  // Second Execution Context
}

В слушателе mouseup первого прямоугольника (горизонтальный) используется второй контекст выполнения (вертикальный), который противоречит интуиции:

function test_func(dir) {
    var X = 9; // variable which helps to track the execution contexts
    if(dir === "horizontal")
       X = 1; // leave at 9 if vertical

    mouseup_vert = function() {}
    mouseup_horiz = function() {
        // Here the value of X I am getting is 9 whereas I am expecting 11
        // QUESTION: Why I am getting the second execution context??
    }
    mousedown_vert = function() {
        // As expected the value of X here is 9
        X=99; 
        // set X to 99 to check if during mouseup same exec context is picked
        document.addEventListener("mouseup", mouseup_vert, false);
    }
    mousedown_horiz = function() {
        // As expected value of X is 1, so using first execution context
        X=11;
        // set this to check if during mouseup I get a value of 11
        document.addEventListener("mouseup", mouseup_horiz, false);
    }

    if (dir === "horizontal") {
        e = document.getElementById("horiz");           
        e.addEventListener("mousedown", mousedown_horiz, false);
    } else {
        e = document.getElementById("vert");            
        e.addEventListener("mousedown", mousedown_vert, false);
    }            
}

1 Ответ

6 голосов
/ 12 февраля 2011

Это потому, что ваши переменные, ссылающиеся на функции, не объявлены с var, поэтому они являются глобальными.

Они перезаписываются вторым вызовом, который закрывается около X значением 9.


РЕДАКТИРОВАТЬ: Вот что эффективно происходит. Для простоты я делаю все переменные в одной области видимости.

   // "a" is referencing a function.
var a = function() { alert( 'a' ); };

   // "b" is referencing the same function that "a" is referencing.
var b = a;

   // The reference "a" holds to the function is being overwritten with a 
   //     reference to a new function.
a = function() { alert( "I'm a new function" ); };

   // "c" is referencing the same function that "a" is referencing (the new one).
var c = a;

   // So what is "b" referencing? It is still the original function, because it
   //    picked up that reference *before* the original reference "a" held was
   //    overwritten.

b(); // alerts 'a'

... или сделать код немного более конкретным для вашего кода:

  // reference a function
var mouseup_vert = function() { alert( "I'm a mouseup function." ); };


  // reference a function
var mousedown_vert = function() {
                    // When this function is invoked, add a listener using
                    //    whatever function is referenced by mouseup_vert
                 document.addEventListener( "mouseup", mouseup_vert, false);
};


  // The function currently referenced by "mousedown_vert" is passed here
  //    as the event handler.
document.addEventListener("mousedown", mousedown_vert, false);


  // Overwrite "mouseup_vert" just for kicks.
mouseup_vert = function() { alert( "I'm a completely different function." ); };


  // NOW trigger a "mousedown" event. What happens? The function passed as the
  //    handler is invoked. 

  // What does that function do? It adds a "mouseup" handler. 

  // Which variable is referenced? "mouseup_vert".

  // What is the current value of "mouseup_vert"? The new function, since we
  //    overwrote the reference to the original.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...