2012-09-20 60 views
3

我是新前端編程。當我在學習Jquery時遇到了這個問題。 這是我下面的代碼問題與jQuery綁定事件

<script type="text/javascript"> 
$(document).ready(function(){ 
    var msg ="hi"; 
    $("#test1").click(function(){alert(msg)}); 
    msg ="hello"; 
    $("#test2").click(function(){alert(msg)}); 
}); 
</script> 
</head> 
<body> 

<button id="test1">test1</button> 
<button id="test2">test2</button> 

在運行這段代碼,無論是打印警報「你好」。我除了點擊第一個按鈕應該用「嗨」來提醒。有人可以解釋爲什麼它的行爲如此嗎?這是禮儀行爲嗎?是否由於範圍限制?請幫助我。

+2

您已改寫了'msg' VAR .. –

回答

1

很多大多數正確的解釋在這裏,但我非常驚訝,沒有人拋出這裏的關鍵概念:關閉。

基本上發生了什麼是當你聲明你的兩個函數,他們聲明的範圍形式爲關閉。這意味着該閉包內的變量仍然可用於函數。換句話說:

$(document).ready(function(){ 
    // this begins a closure 
    var msg ="hi"; 
    // you are simply declaring a function here, not calling it 
    $("#test1").click(function(){alert(msg)}); 
    msg ="hello"; 
    // ditto 
    $("#test2").click(function(){alert(msg)}); 
    // the end of the closure...msg has the value "hello" 
}); 

然後過了一段時間,點擊事件被調用。附加到click事件的函數仍然可以訪問閉包(其中msg的值爲「hello」)。

在閉包中「捕獲」變量值的傳統方法是創建一個"Immediately Invoked Function Expression" (IIFE)。基本上你可以認爲這是創建一個全新的閉包,它包含變量的直接值。你可以重新編寫代碼,使用IIFEs這樣的:

$(document).ready(function(){ 
    // this begins a closure 
    var msg ="hi"; 
    // the following creates an anonymous function with a single parameter 
    // AND invokes it immediately, creating another closure in which the 
    // value of msg1 is "hi". 
    (function(msg1){ 
     $("#test1").click(function(){alert(msg1)}); 
    })(msg); 
    msg ="hello"; 
    // ditto 
    (function(msg2){ 
     $("#test2").click(function(){alert(msg2)}); 
    })(msg); 
}); 

我希望這使得它有點更清楚發生了什麼,以及如何讓你在找什麼。

5

您有範圍問題。

通過你到這對文件準備好,你居然點擊msg === "hello"

+0

我不認爲這是一個問題,看到它的預期的行爲。他要求從DOM就緒處理程序範圍提醒'msg' var,它會提醒其當前值。 –

+0

@FabrícioMatté哈哈我從來沒有說過這是一個問題:-) – Neal

+0

不知道今天尼爾是否在巨魔心情。但+1清楚解釋'=]' –

1

執行JavaScript代碼的代碼點的時間。在這一點上,點擊功能被綁定到兩個按鈕,msg先設置爲hi,然後執行下一行,msg被hello覆蓋。
當點擊被觸發時msg已被覆蓋,從而輸出hello。

儘管這是正確和預期的行爲。您可以通過使用兩個變量或在點擊時(在點擊功能中)設置它們來解決此問題。

+0

另一個選項是範圍變量。 – Nimnam1

+2

我不會稱之爲全局的,因爲它不能從窗口上下文訪問。是的,兩個函數都引用相同的'var',但它的作用域在DOM就緒處理函數中。 –

+0

你是對的。更新了答案 – Horen

0

這是預期的行爲。它通常不直觀,但是javascript是如何工作的。讓你想要的結果的最簡單方法是使用功能,像這樣:

$(document).ready(function(){ 
    var msg ="hi"; 
    $("#test1").click(getCallback(msg)); 
    msg ="hello"; 
    $("#test2").click(getCallback(msg)); 
}); 

function getCallback(msg){ 
    return function(){ 
     alert(msg); 
    } 
} 

msg參數內getCallback對每個呼叫,這將維護每個單獨的調用正確的值單獨msg變量。

+0

你的第二個選項不會工作......它使用並立即執行函數.... – Neal

+0

@neal你是對的。意識到,但被拉開了。只是要刪除它,因爲我沒有時間修復它atm。 –

2

處理程序代碼執行時,msg的值爲「hello」。

或者,您可以將它作爲數據傳遞給處理函數來訪問它..

$(document).ready(function(){ 
    var msg ="hi"; 
    $("#test1").click({msg: msg}, function(e){alert(e.data.msg)}); 
    msg ="hello"; 
    $("#test2").click({msg: msg}, function(e){alert(e.data.msg)}); 
}); 

DEMO:http://jsfiddle.net/h36pf/