首页 > 什么是封闭空间,使用封闭空间的意义何在?

什么是封闭空间,使用封闭空间的意义何在?

学习过用封闭空间写选项卡的实例后,对如下代码感到不知如何理解:

<script>
window.onload=function(){
    var oBox = document.getElementById('box');
    var aBtn = oBox.getElementsByTagName('input');
    var aDiv = oBox.getElementsByTagName('div');
    
    for(var i=0;i<aBtn.length;i++){
        (function (index){
            aBtn[index].onclick=function(){
                for(var i=0;i<aBtn.length;i++){
                    aBtn[i].className='';
                    aDiv[i].style.display='none';
                }
                this.className='on';
                aDiv[index].style.display='block';
            };
        })(i);
    }
};
</script>

我知道“在循环里加事件,事件里不能用i”这件事,但尚未想清楚为什么不能用?以及为什么利用封闭空间这种写法,能够解决这个问题?
希望有人能够通过这个例子,把封闭空间的本质和循环事件里不能用i原因的帮我理清楚


闭包的用法很多 网上随便搜一下一堆 面试笔试都喜欢考的东西
然而对于这种框架 如果用jQuery有更容易理解的写法 就是用data把数据全存在外层div上 每次用的时候去取
闭包毕竟有那么一点点内存泄露的危险


最大的作用,防止全局名空间的污染


<script>
window.onload=function(){
    var oBox = document.getElementById('box');
    var aBtn = oBox.getElementsByTagName('input');
    var aDiv = oBox.getElementsByTagName('div');

    function BindEvent(index){
        aBtn[index].onclick = function(){
            for(var i=0;i<aBtn.length;i++){
                aBtn[i].className='';
                aDiv[i].style.display='none';
            }
            this.className='on';
            aDiv[index].style.display='block';
        }
    }
    
    for(var i=0;i<aBtn.length;i++){
        BindEvent(i);
    }
};
</script>

这样写楼主可以理解否?
还有这个玩意不叫封闭空间, 而是叫 闭包.


你这个是IIFE(Immediately-Invoked Function Expression )

var a = '123';
(function(){
   var a = '321';
    console.log(a);
}());
console.log(a);

输出:

321
123

看个例子:

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function () {
            alert(i);
        };
        document.body.appendChild(link);
    }
}

你随便点击那个都会提示link 5, 为什么呢?因为,i是在循环里面定义的,等你真的触发onclick事件的时候,循环已经执行完了,这个时候i等于5,根本原因在于:JavaScript's scopes are function-level, not block-level,用IIFE的意义在于把循环时的变量传递传到IIFE中的匿名function中,形成它自己范围的一个新的变量。

function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function (num) {
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);
    }
}

这个由点绕,自己多理解吧。


关于闭包,我实在不知道用中文如何描述,我用英语总结一下:

future reference to a outer scope variable creates a closure.
大致意思,对于一个外部变量的“未来引用”(事件处理器绑定的时候,事件处理器还没有被触发)会创建闭包。

when the outer function finish executing, variables in it's local scope are     discarded, so if inner functions need to use such variables in the future, they need to remember those variables.(in software manner, store in somewhere).

当一个外部方法执行完了之后,其本地变量就不复存在了,所以当这个方法里面的内部方法要在将来引用这些本该消失的变量时,就需要把这些变量记住,用编程的话来说,就是存在内存中的某个地方。

下面的代码,在chrome中打开,我们在第10行和第12行加上断点:

<html>
<body></body>
<script>
function addLinks () {
    for (var i=0, link; i<5; i++) {
        link = document.createElement("a");
        link.innerHTML = "Link " + i;
        link.onclick = function (num) {
            console.log(1);
            return function () {
                alert(num);
            };
        }(i);
        document.body.appendChild(link);
    }
}
addLinks();
</script>
</html>


i作为参数传递给匿名function内部变量num, 没有引用外部变量,没有闭包。


里面的匿名function,在未来运行的时候,要用到外部变量num,此时会创建闭包。

【热门文章】
【热门文章】