2011-02-12 37 views
2

這是一個範圍鏈的有趣案例,我沒有在很多文檔中解釋,我發現它很難理解。如果有人可以花時間閱讀下面評論好的代碼,並解釋變量如何得到解決,那將是非常好的Javascript執行上下文,鼠標處理程序中反直觀的範圍鏈

我在文檔上有兩個矩形(DIV)。我在註冊mouseup的mousedown偵聽器上和內部註冊了mousedown的事件偵聽器。奇怪的事情發生在mouseup的監聽器中。

兩個執行上下文是通過調用testfunc兩次的參數不同的值創建的:

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

在所述第一矩形的鼠標鬆開聽者(水平)的第二執行上下文(垂直)正在使用哪個是計數器直觀:

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

回答

6

這是因爲你的變量引用的函數沒有用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. 
+0

沒錯。這些「mouseup_foo」變量都是全局的。他們必須用`var`關鍵字聲明!此外,從事件處理程序內部設置事件處理程序無論如何都將是一個大問題。 – Pointy 2011-02-12 14:25:16