简单理解闭包与立即执行函数

闭包

闭包 是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。——《JavaScript高级程序设计》

首先明确JS中函数的作用域确定的基本原则:

  1. 外部函数作用域不能看到内部函数的作用域;
  2. 内部函数作用域可以看到外部函数的作用域;

那么如何能访问或修改到一个函数内部的变量呢?
函数的return就是这个传送门,可以将一个内部函数送出外部函数。 即使无法直接访问到外部函数内部的变量,也可以通过return出的内部函数去访问或修改外部函数的变量。

用一个简单的例子来解释。

function outerFn(){
    var data = 10
    var innerFn = function(){
          data += 1
          console.log(data)
    }
    return innerFn
}
var result = outerFn()
result()
result()
// 11
// 12

现有一个名为outerFn的函数,它的内部包含一个已经声明的变量data和一个内部函数innerFn。一般情况下,是无法访问或修改data的,但是innerFn可以访问到data,我们通过调用return出的innerFn,就可以间接的去修改和访问到data的数据了。
这样的做法,被总结称为 闭包

为什么要这么做?

  1. 为一个封闭的函数作用域开一个传送门,让外界可以去访问和修改它;
  2. 将部分函数内部的局部变量暴露,按需求进行共享和长期保存。

需要注意的地方

由于内部函数在被访问后一直处于被引用状态,不能够被垃圾回收。在调用完毕后,如上例,将 result = null ,解除innerFn的引用,方便内存释放,是比较好的方式。

立即执行函数

当我们理解了 闭包 的概念后,就会出现一种需求,我们并不需要多次调用闭包函数,甚至并不需要闭包的返回值,仅仅是需要它执行一次。那上述函数最简单的写法是否如下:

function outerFn(){/* code */}()      //SyntaxError: Unexpected token (

很可惜,结果却是报错。

原因

当JavaScript在读取代码时,看到 function 关键字后,就已经认为这是一个函数声明了,而在函数声明之后,是不可以直接加()来执行的。我们要做的就是让js知道这不是一个函数声明即可。

解决方法

很简单,可以用圆括号将整个函数包起来再(),更可以使用简单的判断符号来处理。这样的做法,就称为 立即执行函数

(function outerFn(){/* code */})()
!function outerFn(){/* code */}()
~function outerFn(){/* code */}()
true && function outerFn(){/* code */}()

可以用来做什么?

一般情况下,只对匿名函数使用这种 立即执行函数 。它的核心是 闭包 ,实现的目的有以下几个:
1. 不必为函数命名,避免污染全局变量;
2. 内部形成单独的块级作用域,封装一些私有变量;
3. 内部变量执行完即销毁,不会占用更多的内存。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容