1.什么是闭包?
在JavaScript中,函数内部可以读取全局变量,在函数外部却无法读取函数内的局部变量。
闭包指的是有权访问另外一个函数作用域中的变量的函数,也就是能够读取其他函数内部变量的函数。
⭐ 闭包的本质是函数,有权访问另外一个函数作用域中的变量的函数
1 | function f1(){ |
上述代码中,函数f2
定义在函数f1
的作用域内,因此f1
内部的局部变量对f2
是可见的,但f2
内部的局部变量对f1
是不可见的。那么只要把f2
作为f1
的返回值,就可以在f1
外部读取它的内部变量了。
⭐ 父对象的所有变量,对子对象都是可见的,反之则不成立。
1.1 闭包的作用
- 使函数的内部变量(函数)在函数执行完后,仍然存活在内存中,延长了局部变量的生命周期
- 将变量(函数)定义在闭包中使用,避免污染全局变量
- 定义JS模块
1.2 闭包的缺点
函数执行完后,函数内的变量没有释放,占用内存时间会变长,容易造成内存泄露
2.闭包存在的问题
使用闭包的时候,①引用的变量可能发生变化 ②this指向的问题
2.1 引用变量的变化
1 | function outer () { |
因为每个闭包函数访问变量i是outer执行环境下的变量i,随着循环的结束,i已经变成10了,所以执行每个闭包函数,结果打印10, 10, …, 10。
解决方案:
1 | function outer () { |
此时访问的num,是上层函数执行环境的num,数组有10个函数对象,每个对象的执行环境下的number都不一样。
2.2 this的指向
1 | var object = { |
因为里面的闭包函数是在window作用域下执行的,也就是说,this指向windows,打印undefined。
解决方案:
1 | var name = "The Window"; |
使用that指向object,指定了匿名函数调用时的this指向对象。
闭包会使得 函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
同时闭包会在 父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。