【问题标题】:Why IIFE can fix "cannot set property 'onclick' of null"为什么 IIFE 可以修复“无法设置属性‘onclick’为空”
【发布时间】:2015-12-26 15:40:03
【问题描述】:

我有一段代码如下

<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>

【问题讨论】:

  • 那么元素 left_side 没有子元素,所以它为空。将它放在 IIFE 中应该会产生零差异。
  • 我知道它没有孩子,所以它是空的。我的问题是为什么 IIFE 可以解决这个问题,就像把 $(document).ready 放进去一样
  • @PQThắng,它仍然为空。
  • @PQThắng — 在 JS Fiddle 示例中,您仍然将其配置为运行 JavaScript ONLOAD。 IIFE 没有任何区别。它是 onload 包装器。如果您在问题本身中提供了完整的代码,而不是依赖外部服务(这会增加副作用)来托管您的一半问题,这将是显而易见的。
  • 我看不出有没有 IIFE 有任何区别。

标签: javascript iife


【解决方案1】:

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

原始代码(抛出 TypeError)

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

修改后的代码

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>';
}
&lt;body&gt;&lt;/body&gt;

【讨论】:

  • 你是对的。如果我只将 IIFE 包装到 theLeftside.lastChild.onclick,问题仍然存在
  • @PQThắng 这就是我们从一开始就想告诉你的 ;-)
猜你喜欢
  • 2018-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-22
  • 2021-01-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多