聊聊前端开发中关于闭包的那点事

聊聊前端开发中关于闭包的那点事
今天老大去面试了一个两年工作经验的前端工程师,一个关于js闭包的问题直接将面试的人问懵了,我个人感觉对于一个有两年经验的前端开发人员来说,闭包应该是必须要掌握的。如果只有一年的经验,我可以理解,但是两年及以上,此处省略…。
好了不卖关子了,今天我们就来说说关于javascript的闭包。
我们从三个方面讲解
1.什么是闭包?
2.闭包有什么用?
3.使用闭包需要注意什么?

一.什么是闭包?
我看看了很多的解释,看的人云里雾里的。最后总结了一下,闭包其实就代码编写时呈现的一种特定形式,就是在一个函数中定义并返回了另外一个函数,在这个内部定义的函数中可以访问外面的函数定义的变量,但是外面函数不能访问内部函数定义的变量。

function test1(){
    var a = "abc";
    var b = "efg";
    var test2 = function(a1,b1){
        console.log("a1:"+a1+"--b1:"+b1);
    }
    return test2(a,b);
}

上面这段代码其实就形成了一个简单的闭包。

闭包其实和js的作用域是紧紧相关联的,要想了解闭包还必须首先了解一下js的作用域。
这里我们先不考虑ES6,我们只考虑ES5及以下。

作用域?
作用域其实就是变量或或属性能够起作用的范围,就像我们常说的领空一样,我们国家的战斗机一般只能在我们自己的领空进行巡逻,训练啥的,你如果跑到其他国家的领空去了你这就叫入侵了,这是要出事情的,轻者就像我们外交部常说那样“我们抗议,我们严重抗议,我们坚决反对”然后没了;重者就像土耳其直接将俄罗是的战机干下来一样。当然美帝是一个Bug,不考虑。言归正传,js的作用域分为局部作用域和全局作用域。
局部作用域又叫函数作用域,他只在函数内部生效,定义在该作用域内的变量或属性,就只能在该函数内可以访问。其他的函数想访问,对不起,此领空不开放。

var age="10";
function person(){
    var name  = "wang_yangyang";
}

上面代码中person函数在执行的时候就形成了一个局部作用域,在该作用域中name就是局部变量只有在person中才能访问到,你在person外面是访问不到的。另外就是全局作用域了,顾名思义就是在哪里都可以访问的,由一种普天之下莫非王土的赶脚。
类似上面代码中age说在的作用域就是全局作用域,你在所有全局作用域定义的函数中都可以访问。

二.闭包有什么用?
其实概括起来说闭包主要有两个用处:
1.内存常驻:
我们知道js的垃圾回收机制(GC)是自动回收(标记清除,标记计数),这个我们后面再讲。所谓自动回收就是在程序在运行完后申明的变量就从内存中释放掉了,这是再访问该变量可能就访问不到了,或者说不是你要的结果了,比如:

  var a = [];
  for(var i = 0 ;i<10;i++){
    a[i] = function(){
       console.log(i)
   };
 }
a[1](); //10
a[2](); //10

你会发现无论怎样输出结果但是10,并没有达到我们想要的效果,那这是这是什么原因呢?这是因为当我们执行ai的时候上一次的程序已经执行完了,这个时候i在全局作用域中已经变成了10,当你再执行啊ai时,console.log(i)自然全部就是10了。那要怎么样才能达到我们的目的呢,这个时候其实使用闭包就相当简单了;

var a = [];
for(var i = 0 ;i<10;i++) {
  a[i] = function(i){
           return function(){
               console.log(i);
           }
  }(i)
};
 a[1]()
a[1](); //1
a[2](); //2

上面的代码就够成个一个闭包,这样啊闭包总的变量就会一直在内存中存在,不会被回收,也达到了我们的目的。
2.隔离作用域
我们知道如果我们的项目如果很大的话就必然会使用到很多的变量,如果这些变量管理不好就会造成变量污染,这个时候进行作用域隔离就是必须的了。闭包有一个明显的特征就是可以访问外面的变量,但是外面的变量无法访问内部函数的变量。我们利用这个特征就可以实现作用域隔离。集体实现我们可以参考一下jQuery的实现。大概就是:

(function(window,undefined){
   var jQuery = function(){
   };
   window.jQuery = window.$ = jQuery();
})(window,undefined)

上面的代码形成了一个匿名函数自执行,其实就是一个闭包,我们将window变量和undefined作为参数传进去,然后再将要暴露的属性通过window这个对象作为桥梁暴露到全局作用域中。这样无论你在上面的代码中申明多少变量,只要你没有通过window对象暴露出去,这些申明的变量就永远不会污染到全局变量。建议有一定基础的可以去看看jQuery 的源码,其实它里面的很多实现是非常巧妙的,对我们的js编程提高有很好的效果。
这只是主要的两个用处,闭包还有许多用处,比如在申明自定义对象的时候可以使用,具体情况具体分析,做到活学活用,程序是死的,人是活的。
三.使用闭包需要注意什么?
我们可能会觉得既然闭包这个好那我们能不能大量使用呢!答案是,可以使用,但是不要大量使用,更不可乱用,因为我们知道闭包中的变量是不会被回收的,这样随着变量数量的增加,内存的消耗也会不断的变大,最后有可能出现内存泄漏,导致页面假死,浏览器崩溃等问题。

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值