作用域闭包
什么是闭包?
闭包是基于词法作用域书写代码时产生的自然结果
当函数可以记住并访问所在词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行
闭包是指有权访问另一个函数作用域中的变量的函数
1 |
|
为什么在外部能够访问到内部的值?
这就涉及到JS引擎的垃圾回收机制了
例如上面的例子,foo最终返回的是一个函数,然后再在外部调用bar这个函数
即在自己定义的词法作用域以外的地方执行,也正是因为bar本身要使用这个内部作用域,引擎的垃圾回收会被阻止,这也是为什么说闭包会造成性能浪费
1 |
|
无论通过何种手段将内部函数传递到所在词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包
闭包的应用
在定时器,事件监听器、ajax请求、跨窗口通信、Web Workers或者其他任何的异步(或者同步)任务中,只要使用了回调函数,实际上就是在使用闭包
模块
1 |
|
这里返回的是一个对象字面量,保持内部数据变量隐藏且私有
实际上也可以返回一个内部函数,Jquery和$标识符就是jQuery模块的公共API
模块模式需要必备两个必要条件:
1.必须有外部的封闭函数,该函数至少被调用一次(每次调用都会创建一个新的模块实例)
2.封闭函数必须返回至少一个内部函数,这样内部函数才能在私有作用域中形成闭包,并且可以访问或修改私有的状态
上面的代码CoolModule的模块创建器,可以被任意调用多次,每次调用都会创建一个新的模块实例
如果只需要一个实例,可以对模块进行简单的改进
1 |
|
将模块函数转换成了IIFE,立即调用这个函数并且将返回值赋值给foo
当然也可以更改模块使其接受参数
在现代模块机制中会使用import、module、export来进行模块导入
import可以将一个模块中的一个或多个API导入到当前作用域中,并绑定在一个变量上
module会将整个模块的API导入并绑定到一个变量上
export会将当前模块的一个标识符(变量、函数)导出为公共API