我的功能有什么问题
我不知道为什么它不起作用。如果您提交该行,然后在控制台中使用 console.log ,则 displayWorld() 底部的函数调用可以正常工作。但如果我在代码中调用该函数,它就会中断。
抱歉,这里是错误
Uncaught TypeError: Cannot set property 'innerHTML' of null at displayWorld (index.html:40) at index.html:43
HTML
<!DOCTYPE html>
<html>
<head>
<title>Pacman Demo</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="style.css"></style>
<script type="text/javascript" src='http://code.jquery.com/jquery-1.10.2.min.js'></script>
<script type="text/javascript">
var world = [
[2,2,2,2,2,2,2,2,2,2],
[2,1,1,2,1,1,1,1,1,2],
[2,1,1,2,1,2,2,2,1,2],
[2,1,1,1,1,1,2,1,1,2],
[2,1,1,1,1,1,2,1,1,2],
[2,1,1,1,1,1,2,1,1,2],
[2,1,1,1,1,1,2,1,1,2],
[2,1,1,1,1,1,1,1,1,2],
[2,2,2,2,2,2,2,2,2,2],
];
function displayWorld(){
var output = '';
for(var i=0; i<world.length; i++){
output += "\n<div class='row'>";
for(var j=0; j<world[i].length; j++){
if(world[i][j] == 2)
output += "\n\t<div class='brick'></div>";
else if(world[i][j] == 1)
output += "\n\t<div class='coin'></div>";
if(world[i][j] == 0)
output += "<\n\tdiv class='empty'></div>";
}
output += "\n</div>";
}
console.log(output);
document.getElementById('world').innerHTML = output;
}
displayWorld(); <----- this piece here
</script>
</style>
</head>
<body>
<div id='world'></div>
</body>
</html>
CSS
/*CSS reset settings here*/
*{
margin: 0px;
padding: 0px;
}
body{
background-color: black ;
}
div.row div{
width: 20px;
height: 20px;
display: inline-block;
}
div.brick {
background-color: blue;
}
div.coin{
background: url(coin.gif);
background-repeat: no-repeat;
background-position: center;
}
div.packman{
background: url(mrpacman.gif);
background-repeat: no-repeat;
background-position: center;
}
div.empty{
}
我认为这是因为您在创建 div 标签之前加载了 js 文件,将脚本放在 body 的末尾,这样就可以解决问题
要完全理解为什么会发生这种情况,您应该了解
HTML
+
CSS
+
JS
模型的工作原理。我描述了完整的页面加载和执行逻辑,因为它可能有助于您理解类似的问题。如果您只对当前错误感兴趣,请跳至第 3 点。
-
在构建
CSSOM
之前不会执行任何JavaScript
(以防止FOUC
)。 -
在读取和解析
<head>
之后构建 CSSOM。 这就是为什么您需要将所有样式表和<style>
标签放在<head>
中的原因。如果您将它们放在<body>
中,则 FOUC 可以在 body 中<style>
之前的内容上使用,因为它首先是在没有这些规则的情况下呈现的。 -
<script>
标签一经遇到,就会按出现的顺序读取和执行。已经从<head>
加载的标签在<body>
标签添加到DOM
之前按遇到的顺序执行。<body>
内的<script>
标签在构建DOM
时满足条件时执行, 但在页面其余部分(后面的内容)添加到DOM
之前。
这意味着您的
<script>
标记在
DOM
中创建
<div id="world"></div>
之前执行,并且您的脚本尝试使用此行向其添加内容...
document.getElementById('world').innerHTML = output;
... 会导致错误,因为
document.getElementById('world')
此时返回
null
,而
null
没有
innerHTML
属性。
要修复此问题,您应将脚本放在
<body>
中,位于
#world
div 之后:
*{
margin: 0px;
padding: 0px;
}
body{
background-color: black ;
}
div.row div{
width: 20px;
height: 20px;
display: inline-block;
}
div.brick {
background-color: blue;
}
div.coin{
background: url(coin.gif);
background-repeat: no-repeat;
background-position: center;
}
div.packman{
background: url(mrpacman.gif);
background-repeat: no-repeat;
background-position: center;
}
div.empty{
}
<div id="world"></div>
<script type="text/javascript">
var world = [
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
[2, 1, 1, 2, 1, 1, 1, 1, 1, 2],
[2, 1, 1, 2, 1, 2, 2, 2, 1, 2],
[2, 1, 1, 1, 1, 1, 2, 1, 1, 2],
[2, 1, 1, 1, 1, 1, 2, 1, 1, 2],
[2, 1, 1, 1, 1, 1, 2, 1, 1, 2],
[2, 1, 1, 1, 1, 1, 2, 1, 1, 2],
[2, 1, 1, 1, 1, 1, 1, 1, 1, 2],
[2, 2, 2, 2, 2, 2, 2, 2, 2, 2],
];
function displayWorld() {
var output = '';
for (var i = 0; i < world.length; i++) {
output += "\n<div class='row'>";
for (var j = 0; j < world[i].length; j++) {
if (world[i][j] == 2)
output += "\n\t<div class='brick'></div>";
else if (world[i][j] == 1)
output += "\n\t<div class='coin'></div>";
if (world[i][j] == 0)
output += "<\n\tdiv class='empty'></div>";
}
output += "\n</div>";
}
document.getElementById('world').innerHTML = output;
}
displayWorld();
</script>
或者,您可以通过将脚本包装在内部来延迟其执行
window.onload = function() {
// your script here...
}
这将延迟脚本的执行,直到为
window
触发
load
事件,该事件在遇到
</html>
并且
DOM
完成后立即发生。
注意:
您的脚本不包含任何
jQuery
代码,并且由于您的示例不需要它,因此我将其删除。