深入理解JavaScript 闭包究竟是什么

首先从一个经典错误谈起,页面上有若干个div, 我们想给它们绑定一个onclick方法,于是有了下面的代码

复制代码 代码如下:


<div>
        <span>0</span> <span>1</span> <span>2</span> <span>3</span>
    </div>
    <div>
        <span>0</span> <span>1</span> <span>2</span> <span>3</span>
    </div>


复制代码 代码如下:


$(document).ready(function() {
            var spans = $("#divTest span");
            for (var i = 0; i < spans.length; i++) {
                spans[i].onclick = function() {
                    alert(i);
                }
            }
        });


很简单的功能可是却偏偏出错了,每次alert出的值都是4,简单的修改就好使了

复制代码 代码如下:


var spans2 = $("#divTest2 span");
        $(document).ready(function() {
            for (var i = 0; i < spans2.length; i++) {
                (function(num) {
                    spans2[i].onclick = function() {
                        alert(num);
                    }
                })(i);
            }
        });

2.内部函数

让我们从一些基础的知识谈起,首先了解一下内部函数。内部函数就是定义在另一个函数中的函数。例如:

复制代码 代码如下:


function outerFn () {
    functioninnerFn () {}
}


innerFn就是一个被包在outerFn作用域中的内部函数。这意味着,在outerFn内部调用innerFn是有效的,而在outerFn外部调用innerFn则是无效的。下面代码会导致一个JavaScript错误:

复制代码 代码如下:


function outerFn() {
            document.write("Outer function<br/>");
            function innerFn() {
                document.write("Inner function<br/>");
            }
        }
        innerFn();


不过在outerFn内部调用innerFn,则可以成功运行:

复制代码 代码如下:


function outerFn() {
            document.write("Outer function<br/>");
            function innerFn() {
                document.write("Inner function<br/>");
            }
            innerFn();
        }
        outerFn();


2.1伟大的逃脱

JavaScript允许开发人员像传递任何类型的数据一样传递函数,也就是说,JavaScript中的内部函数能够逃脱定义他们的外部函数。

逃脱的方式有很多种,例如可以将内部函数指定给一个全局变量:

复制代码 代码如下:


var globalVar;
        function outerFn() {
            document.write("Outer function<br/>");         
            function innerFn() {
                document.write("Inner function<br/>");
            }
            globalVar = innerFn;
        }
        outerFn();
        globalVar();


调用outerFn时会修改全局变量globalVar,这时候它的引用变为innerFn,此后调用globalVar和调用innerFn一样。这时在outerFn外部直接调用innerFn仍然会导致错误,这是因为内部函数虽然通过把引用保存在全局变量中实现了逃脱,但这个函数的名字依然只存在于outerFn的作用域中。

也可以通过在父函数的返回值来获得内部函数引用

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdgxss.html