为什么 IIFE 可以修复 "cannot set property 'onclick' of null"
Why IIFE can fix "cannot set property 'onclick' of null"
我有一段代码如下
<body id="main">
<h1>Matching Game</h1>
<p>Click on the extra smile face on the left</p>
<div id="left_side"></div>
<div id="right_side"></div>
<script>
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
quan+=5;
dele();
generateFace();
}
</script>
</body>
这一行theLeftSide.lastChild.onclick
会报错,说"cannot set property 'onclick' of null",因为在javascript引擎扫描它的时候,它还没有任何child然而。这个问题可以通过将这段代码放在$(document).ready里面来解决,我知道。
但是,我也尝试了 IIFE,这意味着将所有这些代码包装在
(function(){
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
quan+=5;
dele();
generateFace();
}
})()
并且还看到问题已解决,但无法弄清楚原因。谁能给我解释一下?
完整的原始代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>part4</title>
<style>
div{
position:absolute;
}
#left_side{
width:500px; height: 500px; border-right:#000 thin inset;
float: left;
}
#right_side{
width:500px; height: 500px;
float:left; left:500px;
}
img{
position: absolute;
}
body{
margin:0px;
}
</style>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.min.js"></script>
</head>
<body onload="generateFace()" id="main">
<h1>Matching Game</h1>
<p>Click on the extra smile face on the left</p>
<div id="left_side"></div>
<div id="right_side"></div>
<script>
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
var e = event;
var theBody= document.getElementById("main");
var post_left =0;
var post_top=0;
var quan = 4;
function generateFace(){
var i =0;
for(i=0; i<= quan; i++){
var img = document.createElement("img");
img.src="smile.png"; post_top=getRandom(); post_left=getRandom();
img.style.top = post_top + "px";
img.style.left = post_left +"px";
theRightSide.appendChild(img);
var clone = img.cloneNode(true);
theLeftSide.appendChild(clone);
}
//var clone = theRightSide.cloneNode(true);
//theLeftSide.appendChild(clone);
var extra = document.createElement("img");
extra.src="smile.png"; post_top=getRandom(); post_left=getRandom();
extra.style.top = post_top + "px";
extra.style.left = post_left +"px";
theLeftSide.appendChild(extra);
};
function getRandom(){
var i = Math.random() * 400 +1;
return Math.floor(i);
};
function dele(){
while(theLeftSide.firstChild != null){
theLeftSide.removeChild(theLeftSide.firstChild);
}
while(theRightSide.firstChild != null){
theRightSide.removeChild(theRightSide.firstChild);
}
};
theBody.onclick = function gameOver() {
alert("Game Over!");
dele();
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
function nextLevel(event){
event.stopPropagation();
quan+=5;
delse();
generateFace();
}
</script>
</body>
</html>
和 IIFE:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>part4</title>
<style>
div{
position:absolute;
}
#left_side{
width:500px; height: 500px; border-right:#000 thin inset;
float: left;
}
#right_side{
width:500px; height: 500px;
float:left; left:500px;
}
img{
position: absolute;
}
body{
margin:0px;
}
</style>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.min.js"></script>
</head>
<body id="main">
<h1>Matching Game</h1>
<p>Click on the extra smile face on the left</p>
<div id="left_side"></div>
<div id="right_side"></div>
<script>
(function(){
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
var e = event;
var theBody= document.getElementById("main");
var post_left =0;
var post_top=0;
var quan = 4;
generateFace();
function generateFace(){
var i =0;
for(i=0; i<= quan; i++){
var img = document.createElement("img");
img.src="smile.png"; post_top=getRandom(); post_left=getRandom();
img.style.top = post_top + "px";
img.style.left = post_left +"px";
theRightSide.appendChild(img);
var clone = img.cloneNode(true);
theLeftSide.appendChild(clone);
}
//var clone = theRightSide.cloneNode(true);
//theLeftSide.appendChild(clone);
var extra = document.createElement("img");
extra.src="smile.png"; post_top=getRandom(); post_left=getRandom();
extra.style.top = post_top + "px";
extra.style.left = post_left +"px";
theLeftSide.appendChild(extra);
};
function getRandom(){
var i = Math.random() * 400 +1;
return Math.floor(i);
};
function dele(){
while(theLeftSide.firstChild != null){
theLeftSide.removeChild(theLeftSide.firstChild);
}
while(theRightSide.firstChild != null){
theRightSide.removeChild(theRightSide.firstChild);
}
};
theBody.onclick = function gameOver() {
alert("Game Over!");
dele();
//theBody.onclick = undefined;
//theLeftSide.lastChild.onclick = undefined;
};
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
quan+=5;
dele();
generateFace();
}
})();
</script>
</body>
</html>
在原始代码段中,generateFace()
在页面加载时被调用。第二段代码直接调用了generateFace()
。与 IIFE 没有关系。请忘记它! :-P 这是您在每种情况下所做操作的简化版本(在 运行 片段之前打开浏览器控制台:
原始代码(抛出类型错误)
console.log('attempting to initialize onclick');
document.getElementById('clickable').onclick = function () {
alert(this.id);
};
console.log('onclick initialized successfully');
function gendiv () {
console.log('gendiv was called');
document.body.innerHTML = '<div id="clickable">click me</div>';
}
<body onload="gendiv()"></body>
修改后的代码
gendiv();
console.log('trying to initialize onclick');
document.getElementById('clickable').onclick = function () {
alert(this.id);
};
console.log('onclick initialized successfully');
function gendiv () {
console.log('gendiv was called');
document.body.innerHTML = '<div id="clickable">click me</div>';
}
<body></body>
我有一段代码如下
<body id="main">
<h1>Matching Game</h1>
<p>Click on the extra smile face on the left</p>
<div id="left_side"></div>
<div id="right_side"></div>
<script>
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
quan+=5;
dele();
generateFace();
}
</script>
</body>
这一行theLeftSide.lastChild.onclick
会报错,说"cannot set property 'onclick' of null",因为在javascript引擎扫描它的时候,它还没有任何child然而。这个问题可以通过将这段代码放在$(document).ready里面来解决,我知道。
但是,我也尝试了 IIFE,这意味着将所有这些代码包装在
(function(){
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
quan+=5;
dele();
generateFace();
}
})()
并且还看到问题已解决,但无法弄清楚原因。谁能给我解释一下?
完整的原始代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>part4</title>
<style>
div{
position:absolute;
}
#left_side{
width:500px; height: 500px; border-right:#000 thin inset;
float: left;
}
#right_side{
width:500px; height: 500px;
float:left; left:500px;
}
img{
position: absolute;
}
body{
margin:0px;
}
</style>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.min.js"></script>
</head>
<body onload="generateFace()" id="main">
<h1>Matching Game</h1>
<p>Click on the extra smile face on the left</p>
<div id="left_side"></div>
<div id="right_side"></div>
<script>
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
var e = event;
var theBody= document.getElementById("main");
var post_left =0;
var post_top=0;
var quan = 4;
function generateFace(){
var i =0;
for(i=0; i<= quan; i++){
var img = document.createElement("img");
img.src="smile.png"; post_top=getRandom(); post_left=getRandom();
img.style.top = post_top + "px";
img.style.left = post_left +"px";
theRightSide.appendChild(img);
var clone = img.cloneNode(true);
theLeftSide.appendChild(clone);
}
//var clone = theRightSide.cloneNode(true);
//theLeftSide.appendChild(clone);
var extra = document.createElement("img");
extra.src="smile.png"; post_top=getRandom(); post_left=getRandom();
extra.style.top = post_top + "px";
extra.style.left = post_left +"px";
theLeftSide.appendChild(extra);
};
function getRandom(){
var i = Math.random() * 400 +1;
return Math.floor(i);
};
function dele(){
while(theLeftSide.firstChild != null){
theLeftSide.removeChild(theLeftSide.firstChild);
}
while(theRightSide.firstChild != null){
theRightSide.removeChild(theRightSide.firstChild);
}
};
theBody.onclick = function gameOver() {
alert("Game Over!");
dele();
theBody.onclick = null;
theLeftSide.lastChild.onclick = null;
};
function nextLevel(event){
event.stopPropagation();
quan+=5;
delse();
generateFace();
}
</script>
</body>
</html>
和 IIFE:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>part4</title>
<style>
div{
position:absolute;
}
#left_side{
width:500px; height: 500px; border-right:#000 thin inset;
float: left;
}
#right_side{
width:500px; height: 500px;
float:left; left:500px;
}
img{
position: absolute;
}
body{
margin:0px;
}
</style>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.11.3.min.js"></script>
</head>
<body id="main">
<h1>Matching Game</h1>
<p>Click on the extra smile face on the left</p>
<div id="left_side"></div>
<div id="right_side"></div>
<script>
(function(){
var theLeftSide = document.getElementById("left_side");
var theRightSide = document.getElementById("right_side");
var e = event;
var theBody= document.getElementById("main");
var post_left =0;
var post_top=0;
var quan = 4;
generateFace();
function generateFace(){
var i =0;
for(i=0; i<= quan; i++){
var img = document.createElement("img");
img.src="smile.png"; post_top=getRandom(); post_left=getRandom();
img.style.top = post_top + "px";
img.style.left = post_left +"px";
theRightSide.appendChild(img);
var clone = img.cloneNode(true);
theLeftSide.appendChild(clone);
}
//var clone = theRightSide.cloneNode(true);
//theLeftSide.appendChild(clone);
var extra = document.createElement("img");
extra.src="smile.png"; post_top=getRandom(); post_left=getRandom();
extra.style.top = post_top + "px";
extra.style.left = post_left +"px";
theLeftSide.appendChild(extra);
};
function getRandom(){
var i = Math.random() * 400 +1;
return Math.floor(i);
};
function dele(){
while(theLeftSide.firstChild != null){
theLeftSide.removeChild(theLeftSide.firstChild);
}
while(theRightSide.firstChild != null){
theRightSide.removeChild(theRightSide.firstChild);
}
};
theBody.onclick = function gameOver() {
alert("Game Over!");
dele();
//theBody.onclick = undefined;
//theLeftSide.lastChild.onclick = undefined;
};
theLeftSide.lastChild.onclick = function nextLevel(event){
event.stopPropagation();
quan+=5;
dele();
generateFace();
}
})();
</script>
</body>
</html>
在原始代码段中,generateFace()
在页面加载时被调用。第二段代码直接调用了generateFace()
。与 IIFE 没有关系。请忘记它! :-P 这是您在每种情况下所做操作的简化版本(在 运行 片段之前打开浏览器控制台:
原始代码(抛出类型错误)
console.log('attempting to initialize onclick');
document.getElementById('clickable').onclick = function () {
alert(this.id);
};
console.log('onclick initialized successfully');
function gendiv () {
console.log('gendiv was called');
document.body.innerHTML = '<div id="clickable">click me</div>';
}
<body onload="gendiv()"></body>
修改后的代码
gendiv();
console.log('trying to initialize onclick');
document.getElementById('clickable').onclick = function () {
alert(this.id);
};
console.log('onclick initialized successfully');
function gendiv () {
console.log('gendiv was called');
document.body.innerHTML = '<div id="clickable">click me</div>';
}
<body></body>