js 匿名函数自执行 之 隐性影响

今天在用面向对象进行编程的过程中,遇到了一个隐藏得很深的坑,在此与大家分享一下,避免以后再犯,也给大家提供一个参考。


先看一下问题代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style type="text/css">
            #contents{
                position: relative;
            }
            #contents div{
                width: 200px;
                height: 200px;
                border: 1px dashed red;
                position: absolute;
                display: none;
            }
        </style>
    </head>
    <body>
        <div id="titles">
    
        </div>
        <div id="contents">
            
        </div>
        
        <script type="text/javascript">
            function SelectCard(btn, div){
                this.btn = btn;
                this.div = div;
            }
            
            SelectCard.prototype.init = function(){
                this.btn.onmouseover = function(){
                    this.div.style.display = "block";
                }.bind(this);
                this.btn.onmouseout = function(){
                    this.div.style.display = "none";
                }.bind(this);
            }
            
            SelectCard.handleJson = function(resultText){

                var objs = JSON.parse(resultText);
                var data = objs.data;
                for(var i = 0, len = data.length; i < len; i++){
                    var btns = document.createElement("button");
                    var divs = document.createElement("div");
                    btns.innerHTML = data[i].title;
                    divs.innerHTML = data[i].content;
                    titles.appendChild(btns);
                    contents.appendChild(divs);
                    var xxk = new SelectCard(btns, divs);
                    xxk.init();
                }
            }
            
            (function(){                
                var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
                xhr.open("GET", "data.json", true);
                xhr.onreadystatechange = function(){
                    if(xhr.readyState == 4){
                        if(xhr.status == 200){
                            SelectCard.handleJson(xhr.responseText);
                        }
                    }
                }
                xhr.send(null);
            })();
                        
        </script>
    </body>
</html>

已知,所获取的 data.json数据无误,且亦无拼写错误和功能性错误。


乍一分析,其实也找不出到底是什么原因导致页面无法输出,通过查看控制台出现如下报错:

error1

经过进一步查看可以看到,SelectCard.handleJson 函数中所传入的参数,并不是我们所期望的 xhr.responseText 数据,而是一个匿名函数

error2

通过调试获取所传入的参数resultText并向控制台输出

test1

查看控制台输出结果我们可以发现所传入的参数居然是它下面的 自执行的匿名函数 本身,而非我们所期望的 xhr.responseText

test2

那么问题来了,为何我们所设定的 “自执行的匿名函数” 会被当做参数传到了上面的函数中呢?

在平常编程的过程中,我们常常会在一句话的末尾加上分号来表示这句话的结束,然而对于函数,我想大部分人应该习惯性的不会加分号来进行分隔,因为函数与函数之间,函数与变量之间即使没有分号,也不会对彼此产生任何影响。

然而,有一个东西写在函数后却会对前面的函数产生影响,而且一般很难察觉,它就是 自执行的匿名函数

由于这一匿名函数被设定为自执行,这就使得这个匿名函数无形中被 括号 包裹起来,即使与它上面的函数有换行的分隔也会被当做参数传入它上面的函数中,这一隐性影响使得 我们始终无法获得 自执行的匿名函数中的目标参数,因为它上面的函数已经把整个自执行的匿名函数当做了要传入的参数。

那么,肯定有人会说,把这个自执行的匿名函数放到他上面的函数的前面不就好了?

这确实是一个方法,不过你仔细看看上面提供的问题代码会发现,这个自执行的匿名函数的前一个函数的前面又是一个函数,那么这个自执行的匿名函数便又被当做了参数传入上面的函数中,只有当调整位置后的 自执行匿名函数 的前面再找不到函数的时候,这个方法才是有效的。

不过最好的方法是:

保证 -自执行的匿名函数- 的前面一句话的末尾始终有 -分号- 即可。

这样的话,即使这一 自执行的匿名函数 前面是函数,也不会有任何影响了。

代码修改处

以上纯属个人学习总结,如有疏漏或者不足之处还望指正,谢谢!

推荐阅读更多精彩内容