2012-07-28 37 views
3

我對Jquery有相當不錯的理解,但決定在JavaScript內部挖掘,因爲我對「原始」JavaScript沒有理解。
所以這裏是我的問題:在文件加載我的功能執行罰款和警報:'你好我的名字是約翰'但按鈕點擊它警報的只是:'你好我的名字是'。我的問題是爲什麼會發生這種情況,我該如何解決?
我知道我可以通過將我的變量INSIDE添加到我的函數來修復它,但是有沒有辦法調用我的函數(腳本類型之後的變量)聲明的FIRST變量

Fiddle here
我的代碼:如何正確提醒我的變量

<!DOCTYPE html> 
<head> 
<script type="text/javascript"> 

//If I try to call this variable WILL NOT WORK:(

var name ='John'; <--SO HOW CAN I CALL THIS VARIABLE TO MY CLICK FUNCTION?--> 

function displayName(name) 
{ 
//If I put my variable like this WILL WORK fine... 
//var name ='John'; 
alert('Hi I am '+name); 

} 

//This function works on document load 
//displayName(name); 
</script> 
</head> 
<body> 

<!--This doesn't work well if variable is OUTSIDE my function:(--> 
<button type="button" onclick="displayName(name)">Display Name</button> 
</body> 
</html> 

回答

15

您的代碼實際上是很好,你只是選擇了一個不幸的名稱爲全球:name。如果將其更改爲其他(如foo),它的工作原理:http://jsfiddle.net/6nuCx/1/

造成這種情況的原因有點模糊。全局變量成爲window對象的屬性。但window對象已經有一個名爲name的屬性,它是該窗口的名稱。我很驚訝地發現你的代碼沒有工作,因爲我希望你的代碼覆蓋窗口的名字。但顯然不是。 (這就是爲什麼它是最好避免全局變量一個偉大例子。)無論如何,選擇不同變量名,一個不與現有name財產衝突,梳理出來。

但是你沒有在你的代碼的東西,可能是不明顯的,所以讓我們深入到多一點深深的(在這裏我使用了foo版本,以避免混亂):

// Here, you're defining a global variable called `foo` 
var foo ='John'; 

// Here you have a global function, `displayName`, which accepts an 
// *argument* named `foo` 
function displayName(foo) 
{ 
    // Here, within the function, the symbol `foo` refers to the 
    // *argument*, not to the global. The global is *hidden* by 
    // the argument (this is called "shadowing" -- the local 
    // "shadows" the global). 
    alert('Hi I am '+foo); 
} 

,並在你的HTML:

<!-- Here, `foo` refers to the global variable --> 
<button type="button" onclick="displayName(foo)">Display Name</button> 

如果我們改變參數的名稱可能是清晰的:

var foo ='John'; 

function displayName(f) 
{ 
    alert('Hi I am '+f); 
} 

和HTML是不變的:

<!-- Here, `foo` refers to the global variable --> 
<button type="button" onclick="displayName(foo)">Display Name</button> 

在上面,我說,這是最好的避免全局變量,你的問題是,爲什麼一個很好的例子。那麼我們該怎麼做?那麼,主要是通過避免DOM0處理程序(如您的onclick中的那個)。這裏是你會如何改寫你的提琴:Live copy

<!DOCTYPE html> 
<html> 
<head> 
</head> 
<body> 
<button id="theButton" type="button">Display Name</button> 
<script type="text/javascript"> 
// Start a "scoping function" 
(function() { 
    // Everything within this function is local to the function, 
    // not global 
    var name = 'John'; 

    function displayName(n) 
    { 
     alert('Hi I am ' + n); 
    } 

    // Instead of the onclick= in the markup, hook up here in 
    // the code 
    document.getElementById("theButton").onclick = function() { 
     displayName(name); 
    }; 
})(); 
</script> 
</body> 
</html> 

注意我們是如何自由使用name,因爲我們沒有創造或全局交互。另外請注意,我在代碼之後的這個按鈕,因爲代碼假定按鈕已經存在。

更好的是,使用addEventListenerattachEvent來連接處理程序。

var btn = document.getElementById("theButton"); 
if (btn.addEventListener) { 
    btn.addEventListener("click", handler, false); 
} 
else if (btn.attachEvent) { 
    btn.attachEvent("onclick", handler); 
} 
else { 
    // Punt! 
    btn.onclick = handler; 
} 

function handler() { 
    display(name); 
} 

正如你所看到的,我們必須同時處理,因爲舊版本的IE(或「兼容模式」較新的)不具有addEventListener。這是使用像jQuery這樣的庫的一個原因,但我知道你試圖擴大你的理解,沒有一個,並有充分的理由。最好的!


最後,你問:

我知道,我可以把我的變量在我的功能修復它,但有一個方法來調用我的函數外聲明我的第一個變量(變量就在腳本類型之後)?

以上都沒有答案。 :-)答案是:是的,你可以參考它直接,通過去除陰影,全球的說法:Live example

<!DOCTYPE html> 
<html> 
<head> 
<script type="text/javascript"> 
var foo ='John'; 

// Note: No argument declared 
function displayName() 
{ 
    // Because the argument doesn't shadow it, we can refer 
    // to foo, because foo is declared in an *enclosing 
    // context* 
    alert('Hi I am '+foo); 
} 
</script> 
</head> 
<body> 
<!-- Note we don't pass any argument ------v --> 
<button type="button" onclick="displayName()">Display Name</button> 
</body> 
</html> 
+0

@Crowder輝煌 – codingbiz 2012-07-28 17:52:53

+0

非常好的答案!我很感激THX! – 2012-07-28 17:54:34

+0

這很好!另一件事是OP不能訪問全局變量,因爲它被本地變量所影響。但是,由於他通過函數調用傳遞了全局變量,它本應該起作用。 – 2012-07-28 17:56:37

0

試試這個:

var name ='John'; 

function displayName() 
{ 
alert('Hi I am '+name); 

} 

</script> 
</head> 
<body> 

<button type="button" onclick="displayName()">Display Name</button> 
</body> 
</html>