闭包和作用域链
闭包是指有权访问另一个函数作用域中的变量的函数。(《JavaScript高级程序设计》7.2闭包)
所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链。和其他大多数现代编程语言一样,JavaScript也采用词法作用域(lexical scoping),也就是说,函数的执行依赖于变量作用域, 这个作用域是在函数定义时决定的,而不是函数调用时决定的。(《JavaScript权威指南》8.6闭包)
当JavaScript需要查找变量的x的值的时候,它会从作用域链中的第一个对象开始查找, 如果这个对象没有名为x的属性,就会继续查找链上下一个对象,最后到全局作用域,如果全都没有找到就会抛出一个引用错误(ReferenceError)异常。
示例
1 | function closure() { |
closure函数返回了一个匿名函数,将其赋值给f,多次调用f,发现closure函数内的count累计增加。
当我们想打印全局作用域中的count时,报错了。由于作用域是在函数定义时决定而不是函数调用时决定的,f return的变量是closure函数作用域内的count,而不是全局作用域的count。
总结
- 作用:
- 延长局部变量的生命周期
- 让函数外部能操作内部的局部变量
- 闭包的应用场景:
- 模块化
- 循环遍历加监听
- 柯里化
- JS框架(jQuery)大量使用了闭包
- 缺点:
- 变量占用内存的时间可能会过长
- 可能导致内存泄露
- 解决:及时释放 : f = null; //让内部函数对象成为垃圾对象
想要通过更多实例来理解闭包,可以看大佬的这篇文章理解js闭包。
GitHub Issues