2012-07-28 38 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>