JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里。
在JS中函数作为普通对象进行传递
什么是闭包?(属于一种特殊的作用域,称为 静态作用域)
简单来说,闭包是指可以访问另一个函数作用域变量的函数,一般是定义在外层函数中的内层函数。(函数和声明该函数的词法环境的组合)子函数所在的父函数的作用域不会被释放。
为什么需要闭包?
使用闭包主要是为了设计私有的变量和方法。闭包的优点可以避免全局变量的污染,让变量始终保存在内存中,缺点是会常驻内存,增大内存的使用 量,使用不当会造成内存泄漏。
特点
- 定义外层函数,封装被保护的局部变量。
- 定义内层函数,执行对外部函数变量的操作。
- 外层函数返回内层函数的对象,并且外层函数被调用,结果保存在一个全局的变量中。
特性
- 函数嵌套函数,内层函数被返回。
- 函数内部可以引用外部的参数和变量,以及外部函数能访问的所有变量和函数。但是,外部函数却不能够访问定义在内部函数中的变量和函数。
- 参数和变量不会被垃圾回收机制回收。
实例
1 | var add = (function () { |
1 | var arr=['one','two','three'] |
1 | var arr=['one','two','three'] |
避免使用过多的闭包,可以用let关键词,每个闭包都绑定了块作用域的变量,这意味着不再需要额外的闭包。
1 | var arr=['one','two','three'] |
1 | // setTimeout(code, milliseconds, param1, param2, ...) |
经典问题
多个子函数的[[scope]]都是同时指向父级,是完全共享的。因此当父级的变量对象被修改时,所有子函数都受到影响。
解决:
- 变量可以通过 函数参数的形式 传入,避免使用默认的[[scope]]向上查找
- 使用setTimeout包裹,通过第三个参数传入
- 使用 块级作用域,让变量成为自己上下文的属性,避免共享