闭包基本形式与作用

86 阅读2分钟

关于闭包作用的说法五花八门,俗话说一招鲜吃遍天,与其要集百家之长不如先总结出合适自己用的。

特此总结三个部分:

1.闭包基本形式 2.闭包延长变量生命周期 3.闭包创建私有作用域

1.闭包基本原理及形式

闭包是什么?简而言之就是在方法里面返回一个方法

image.png 这个就是一个简单的闭包表现形式。

2.闭包延长变量生命周期

我们可以以下面这个例子继续深入:

image.png

写完后可以打开浏览器及逆行调试,发现全局变量a是在script范围内声明的不会被回收的变量,而b是声明在local内函数执行完会被回收的局部变量。

image.png

ES5之前,JS代码在运行的时候会生成一个临时的变量对象AO,而ES5之后一个叫词法环境(Lexical Environments)的定义取代了AO,为了方便继续使用AO代称。

JS代码运行时生成AO,AO存储所有的函数以及局部变量,而全局变量是不会存储在AO内的。

AO内的局部变量在函数运行完后就会被回收,而全局变量则不会。

以下面的例子具体说明闭包延长变量生命周期:

image.png

可见,在outter函数内返回的inner函数只返回了局部变量a1,在调试中发现,被保存下来的只有闭包中的a1和上文的全局变量a。

image.png

闭包中只返回了局部变量a1,把a1放入了内存中,因此a1被保存了下来。 因此,闭包可以将局部变量保存在内存中,常驻内存,所以闭包会对内存产生一定的消耗。 推荐使用完闭包后手动回收闭包,使用完变量后手动为它赋值为null。

3.闭包创建私有作用域 Vue 中的 data()为什么是一个函数呢? data()就是一个闭包的设计。 众所周知,vue是一个单页面应用,一个页面中会有很多组件,而每一个组件都会有一个data()

image.png

相当于就是利用闭包给每一个组件都建立了一个私有作用域。 如果只用普通对象来组建组件,就会使各个组件间的变量相互污染。

用计数器举个例子

image.png

console.log(counter1.value()); // 0 counter1.add(); counter1.add(); counter2.add(); console.log(counter1.value()); // 2 console.log(counter2.value()); // 1

可见,同一个闭包不同的引用,拥有各自的词法环境,有用各自的作用域。 counter1和counter2的私有变量不会互相影响。

闭包和面向对象编程的理念 ---- 数据的隐藏和封装,拥有很大相似度。