javascript闭包机制
定义
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
从开始学习JavaScript开始就开始接触闭包,到开始工作对闭包的理解一直懵懵懂懂,查询各种文档和大牛的分析(都没看懂,哈哈,可能说的太深奥了),对闭包的解释有很多种
闭包可以定义私有变量,避免被意外修改 闭包可以避免变量被回收 闭包可以避免全局变量污染 还有人说你写得每个方法都是一个闭包
看了很多解释,每次都觉得自己理解了,其实都不太理解,而是理解了一部分(当然可能到现在对闭包的理解还是不全面,以后还要多多学习)
其实上面说的都是闭包的用法,闭包可以解决这些问题,所以我们觉得很奇怪,理解不了
首先拿一个很经典的例子 计数器
//第一种写法(全局变量法) var count = 0 function add() { return ++count } add() // 1 add() // 2 add() // 3 // 第二种写法(闭包法) var add = (function add() { var count = 0 return function() { return ++count } })() add() // 1 add() // 2 add() // 3
这就是一个闭包
那么上面两种计数器的写法有什么区别呢,
第一种全局count是全局变量,会造成全局变量污染(当业务需求有很多需要用这种方法实现的时候,会定义很多全局变量才行);而第二种不存在这种问题 第一种count因为是全局变量,谁都可以修改,会导致无法追溯到底谁改变了他,或者可能会被意外改变,很难维护 都是计数器,功能一样,实现方式不同
那么说到现在,什么才是闭包呢
闭包可以定义私有变量,避免被意外修改
经过上面的例子我们可以看到,我们可以直接访问到count或者修改count的值么,显而易见不能,我们仅仅是获得了经过(包含)count的计算返回值而已,所以在这里(闭包)就有了私有变量的概念
闭包可以避免变量被回收
这里牵扯到JavaScript的垃圾回收机制(不晓得的同学可以移步去看看js的垃圾回收)。js有两种情况会被当成垃圾回收掉
当变量没有被引用的时候,就会被回收 当变量被循环引用,没有被其他引用(其实就是一个闭环引用)时,也会被垃圾回收掉
而在闭包中,count一直在被内层函数引用,无法释放,所以就无法被垃圾回收(看到这里有同学可能会说,那大量的闭包会不会造成内存泄漏 @_@ ,想了解更深层次,可以继续探讨哦,在这里就不详解喽)
闭包可以避免全局变量污染
答案显而易见,闭包是闭环,变量都定义在函数内,且不引用任何外部函数
还有人说你写得每个方法都是一个闭包
这个解释不知道大家理解不,如果这句话成立,嘿嘿。那么我们看看第一种《计数器》的实现方式
//第一种写法(全局变量法) var count = 0 function add() { return ++count } add() // 1 add() // 2 add() // 3
这也是闭包,那你这不模棱两可,前后不搭么?不是的,这也是闭包,可以这么理解,但是我们也可以不叫他闭包。叫他闭包是因为我们可以报全局看做是一个函数,那么全局就形成了闭包了。但是这也没啥意义,所以你可以这么理解,但是不要用到实际开发中,哈哈
最后,总结一下(别人都总结,我也总结)
闭包无处不在,我们很多时候都在使用闭包,因为他能让我们写出更好、更优雅、更易维护的代码