JavaScript全局变量不按预期工作。有帮助吗?

6

我是一个新手,正在学习Javascript。我遇到了一个全局变量的问题。虽然代码看起来没问题,但我无法弄清楚为什么全局变量不起作用。请帮助我解决这个问题。 首先,我简要解释一下代码。我有一个页面上的文本,当单击时会变成文本字段。当我在函数体内定义变量时,代码开始正常工作。但是,当这些变量像以下代码一样在全局范围内定义时,控制台会显示此错误:变量未定义。以下是我的代码:

<!DOCTYPE HTML>
<html>
<head>
<title>Span to Text Box - Demo - DOM</title>
<script type="text/javascript" language="javascript">
var textNode = document.getElementById('text');
var textValue = textNode.firstChild.nodeValue;
var textboxNode = document.getElementById('textbox');
var doneButton = document.getElementById('done');
function change()
{
   textboxNode.setAttribute('value', textValue);
   textNode.style.display = 'none';
   textboxNode.setAttribute('type','text');
   doneButton.setAttribute('type','button');
}
function changeBack()
{
   textNode.firstChild.nodeValue = textboxNode.value;
   textNode.style.display = 'block';
   textboxNode.setAttribute('type', 'hidden');
   doneButton.setAttribute('type','hidden');
}
</script>
</head>

<body>
<p id="text" onClick="change()">Click me!</p>
<form onSubmit="return false;">
  <input type="hidden" id="textbox" />
  <input type="hidden" id="done" onClick="changeBack()" value="Done" />
</form>
</body>
</html>

请帮忙!非常感谢。


1
虽然与您的问题没有直接关系,请不要像这样使用全局JavaScript变量 - 而是确保它们被命名空间化。更多详细信息请参见http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html。 - ziesemer
1
@ziesemer 谢谢,我已经阅读了你推荐的文章。 - Naeem Ul Wahhab
每个 JavaScript 程序员都应该知道什么?我想与这里的所有朋友分享这篇最有用的文章。这是链接:https://dev59.com/r3E85IYBdhLWcg3wwWQb - Naeem Ul Wahhab
2个回答

5
正如Adam所说,问题在于您在文档加载之前就运行了javascript。有许多方法可以解决这个问题,但最简单的方法是将您的javascript代码移到body的末尾,这样文档在您的代码运行之前就已经被解析并准备好了,如下所示:
<!DOCTYPE HTML>
<html>
<head>
<title>Span to Text Box - Demo - DOM</title>
</head>

<body>
<p id="text" onClick="change()">Click me!</p>
<form onSubmit="return false;">
  <input type="hidden" id="textbox" />
  <input type="hidden" id="done" onClick="changeBack()" value="Done" />
</form>

<script type="text/javascript" language="javascript">
var textNode = document.getElementById('text');
var textValue = textNode.firstChild.nodeValue;
var textboxNode = document.getElementById('textbox');
var doneButton = document.getElementById('done');
function change()
{
   textboxNode.setAttribute('value', textValue);
   textNode.style.display = 'none';
   textboxNode.setAttribute('type','text');
   doneButton.setAttribute('type','button');
}
function changeBack()
{
   textNode.firstChild.nodeValue = textboxNode.value;
   textNode.style.display = 'block';
   textboxNode.setAttribute('type', 'hidden');
   doneButton.setAttribute('type','hidden');
}
</script>

</body>
</html>

1
jfriend00,谢谢你的回复,真的帮助我解决了这个问题。你们这些人太好了。 - Naeem Ul Wahhab

4
错误很可能是由于在DOM节点准备就绪之前抓取它们导致的:
var textNode = document.getElementById('text');

这很可能是因为DOM元素尚未创建而返回了nullundefined
将此脚本放在的末尾应该可以解决问题。
或者,如果您想要使用jQuery,则可以在其中完成所有操作。
$(document).ready(function() {
    var textNode = document.getElementById('text');
}

2
+1 因为我认为你是正确的,但虽然我喜欢jQuery,但我不会仅建议在onload时使用它,尤其是可以完全没有onload完成的情况下。 - Nicole
2
@Renesis - 我只是想给OP尽可能多的选择。我不想成为那个仅仅推荐jQuery的人 :) - Adam Rackis
我同意这个答案。问题不在于全局变量,而在于你的时机。 - Zoidberg
2
@capricorn - 很高兴为您服务。jQuery 是一个非常棒的库,可以简化许多繁琐的事情。但是如果您只是将其添加到项目中以解决这个单一问题,请记住,您也可以通过将脚本移到 <body> 的底部来解决它。 - Adam Rackis
2
@capricorn - 不,那样做不能解决问题。问题在于你的DOM元素还没有准备好,所以document.getElementById返回null。要解决这个问题,你可以将脚本移到body底部,这样它将在body被解析并且dom准备就绪后运行,或者使用上面描述的jQuery构造方法。 - Adam Rackis
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接