为什么IIFE可以修复“无法设置属性'onclick'of null”

时间:2015-12-26 15:40:04

标签: javascript iife

我有一段代码如下

<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会抛出一个错误,说“无法设置属性'onclick'of null”,因为当javascript引擎扫描它时,它还没有任何子节点。这个问题可以通过将此代码放在$(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>

1 个答案:

答案 0 :(得分:2)

在原始代码中,在页面加载时调用generateFace()。在第二段代码中,直接调用generateFace()。与IIFE没有任何关系。请忘了! :-P以下是您在每种情况下所做工作的简化版本(在运行代码段之前打开浏览器控制台):

原始代码(抛出TypeError)

&#13;
&#13;
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>';
}
&#13;
<body onload="gendiv()"></body>
&#13;
&#13;
&#13;

修改后的代码

&#13;
&#13;
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>';
}
&#13;
<body></body>
&#13;
&#13;
&#13;