JavaScript 再谈闭包

之前有整理过一版关于闭包的概念,但感觉思路不是很清晰,是临时想起一些例子来讲的,今天再次来讲一下闭包。

 

闭包:

函数嵌套函数,内部函数可以引用外部函数的参数和变量

function aaa(a){
    var b=5;
    function bbb(){
        alert(a);
        alert(b);
    }
}    

 在上面的例子当中,bbb函数是可以访问到aaa函数中的a和b的,同时,JS中的垃圾回收机制也不会回收a,b。

复制代码
function aaa(){
    var a =5;
    function bbb(){
        alert(a);
    }
    return bbb;
}

var c = aaa();
c();
复制代码

可以看到此时调用c()是可以弹出5的,即a在调用aaa()之后是没有被回收的。即常驻内存。

 

闭包的好处:

1 希望一个变量可以长期驻扎在内存,之前已经说明。

2 避免全局变量污染

var a=1;
function aaa(){
    a++;
    alert(a);
}
aaa();    //2
aaa();    //3

此时函数aaa访问的是全局变量a,那么就很容易被其他函数或程序修改。那么可以使用一下代码来避免这个问题

复制代码
function aaa(){
    var a=5;
    return function(){
        a++;
        alert(a);
    }
}
var b=aaa();
b();    //6
b();    //7
alert(a)  //error
复制代码

以上的例子中可以看出已经把a放进函数里作为一个局部变量被引用,a也会常驻内存,不会被垃圾回收清理。

还可以将其改写成函数声明表达式:将function用括号包围起来做到即时调用,并且减少全局变量的污染,实现代码模块化(即该代码不会因外界条件而改变结果)

复制代码
var b=(function() {
    var a=5;
    return function() {
        a++;
        alert(a);
    }
})();
b();    //6
b();    //7
alert(a)  //error
复制代码

3 私有成员

复制代码
var aaa=(function(){
    var a =1;
    function bbb(){alert(++a);}
    function ccc(){alert(++a);}
    return{
        b:bbb,
        c:ccc
    }

})() ;
alert(aaa.b);    //2
alert(aaa.c);    //3
alert(a);          //error
alert(bbb);      //error
alert(ccc);       //error
复制代码

aaa内的函数和变量只能通过aaa来访问,外部是访问不到的,由此实现了私有成员的创建。

4 循环 索引 作用域延伸

复制代码
//有一个3个<li>标签的页面,需要绑定点击事件,弹出对应的序号。

windows.onload=function(){
    var aLi=document.getElementByTagName('li');
    for(var i=0;i<aLi.length;i++){
        aLi[i].onclick = (function(i){
            return function(){alert(i);}
        })(i);
    }
}
复制代码

当然在ES6中使用let替代var也可以解决这个问题。所以在支持ES6的浏览器中能用let的地方就不要用var。

 

还有一个需要注意的地方:

IE下回引发内存泄漏

//假设有个id为div1的div
window.onload=function(){
    var oDiv=document.getElementById('div1');
    oDIv.onclick=function(){
        alert(oDiv.id);
    };
}

在上述情况中,DOM树中的元素被更深层级的调用,会导致关闭页面后无法释放内存的问题,最终会导致内存泄漏。

要想解决这个问题也是十分的简单,只需要在关闭界面的时候强制解除对元素的引用。即:

复制代码
//假设有个id为div1的div
window.onload=function(){
    var oDiv=document.getElementById('div1');
    oDIv.onclick=function(){
        alert(oDiv.id);
    };
//以下为添加解除程序
    window.onunload=function(){
        oDiv.click=null;//或者oDiv=null也可以。
    }
}
复制代码

以上便是闭包的所有相关知识。总结一下:

1 闭包的含义:函数中嵌套函数,嵌套的内部函数可以访问外部函数的参数和变量。

2 闭包的作用:

  1 避免全局变量的污染。

  2 创建私有成员(函数和变量)。实现代码模块化

  3 作用域的延伸,也是变量常驻内存的一种体现。

 

 

 
posted @   KeepLearning_!  阅读(195)  评论(0编辑  收藏  举报
编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 上周热点回顾(1.20-1.26)
· 【译】.NET 升级助手现在支持升级到集中式包管理
点击右上角即可分享
微信分享提示