闭包的官方定义时有权访问另一个函数作用域中的变量的函数。
闭包有两种用法:函数作为返回值,函数作为参数传递
第一:函数作为返回值
上面代码中,bar函数作为fn函数的返回值,赋值给了变量f1,因此执行f1()就是执行bar函数,执行bar函数时,变量max从fn作用域中去取。
第二:函数作为参数传递
这种一般是自执行的匿名函数
上面代码中,fn函数作为参数赋值给自执行匿名函数里的f参数,因此执行f(15)就是执行fn(15),执行fn(15)时,max的值取全局作用域中的10。
另外,闭包的另一个作用就是可以让变量常驻内存,一般而言函数执行完,该函数的执行环境应该被销毁,但由于闭包的存在,函数的执行环境不会立即被销毁。
上面代码中,第一步,代码执行前生成全局执行环境,并在其中对变量进行赋值,此时全局执行环境处于活动状态。
第二步,执行第17行代码,fn函数作为变量赋值给了f1变量,调用fn(),产生了fn函数的执行环境,此时fn执行环境处于活动状态
第三步,执行完17行代码,按理说应该销毁fn函数的执行环境,但此时不能这么做,因为,执行fn函数时,返回的是一个函数。而函数的特别之处在于可以创建一个独立的作用域。
并且bar函数体中,还有一个自由变量要引用fn作用域中的值。因此fn执行环境不能被销毁,毁了之后max就找不到值了。
第四步,执行18行代码,此时全局执行环境和fn执行环境都处于活动状态,执行完18行代码,全局执行环境中的max变量被赋值为100
第五步,执行20行代码,因为17行代码中fn函数被赋值给了f1变量,因此执行f1函数就是执行fn函数,即执行bar函数,此时bar函数处于活动状态。
执行bar函数时,max是自由变量,需要到创建bar函数的作用域中去查找,因此找到了fn作用域,即max的值为10。
从这里可以看出,创建bar函数是在执行fn函数时创建的。fn早就执行完了,但fn的执行环境依然存在于内存中,因此执行bar(15)时,max可以查找到,如果fn执行环境销毁了,那max就找不到了。
结论:使用闭包,会增加内存消耗。
如果使用不当,还会造成内存泄漏问题。