0
点赞
收藏
分享

微信扫一扫

JavaScript系列之闭包详解

犹大之窗 2022-03-10 阅读 29

目录


1、什么是闭包了?

函数和函数能访问的局部变量就构成了一个闭包。

有个读者就感到疑惑了,闭包就这么简单吗?

【我听说闭包是需要函数嵌套,并且 return 一个函数的】

比如如下这样的:

function getLocal() {
  var local = 1
  function funLocal() {
    local++
    return local
  }
  return funLocal
}

var func = getLocal()
func()

这里确实有闭包,local 和函数 funLocal 就组成了一个闭包。

2、为什么需要函数嵌套了?

是因为需要局部变量,所以才把 local 放在一个函数里,如果不把 local 放在一个函数里,local 就是一个全局变量了,达不到使用闭包的目的,所以函数套函数只是为了造出一个局部变量,跟闭包无关。

3、为什么要 return funLocal 呢?

因为如果不 return,你就无法使用这个闭包。把 return funLocal 改成 window.funLocal = funLocal 也是一样的,只要让外面可以访问到这个 funLocal 函数就行了。

所以 return funLocal 只是为了 funLocal 能被使用,也跟闭包无关。

4、闭包有什么用了?

这部分的摘自学习Javascript闭包(Closure)

闭包可以用在许多地方。它的最大用处有两个,一个可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

怎么来理解这句话呢?请看下面的代码。

  function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000

在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

5、闭包的优势

①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突

②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)

③匿名自执行函数可以减少内存消耗

6、闭包的不足

①其中一点上面已经有体现了,就是被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null

②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响

7、关于闭包的谣言

闭包会造成内存泄露?

错。

说这话的人根本不知道什么是内存泄露。内存泄露是指你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。

闭包里面的变量明明就是我们需要的变量(lives),凭什么说是内存泄露?

这个谣言是如何来的?

因为 IE。IE 有 bug,IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量。

这是 IE 的问题,不是闭包的问题。参见司徒正美的这篇文章。


后记

在这里插入图片描述

举报

相关推荐

0 条评论