闭包
概念:闭包就是函数能够记住并访问它的词法作用域,即使当这个函数在它的词法作用域之外执行时。简单来说就是在函数的外部可以使用到其内部的变量,可以将该函数理解为一个闭包。
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 2 看到闭包了,妈妈
原理:js中的变量,函数在执行的时候都会被加载到栈中,执行完毕弹出,当使用闭包的时候,函数执行完成后,不会弹出,因为其他的地方还要加载其内部变量
闭包的特点
-
闭包的变量不能及时被释放,一直存在即占用空间,造成内存泄漏
-
可以形成私有变量,只能被特定的函数使用,避免变量污染
解释一下内存泄漏: 存在一些无法访问的变量或对象,它们占用的内存却无法被回收。这会导致应用长期运行后内存占用越来越高,甚至导致应用崩溃。
闭包+循环
展示闭包怎么能少的了for循环。
for (var i=1; i<=5; i++) {
setTimeout( function fn(){
console.log( i );
}, i*1000 );
}
这段代码的含义是,我们希望他每秒打印一次i,并且i为1,2,3..5,但实际上你运行这段代码,会得到5次被打印的“6”。
首先解释一下6从哪里来的,6为for循环的终止条件,也就是说for循环走完时的最终值。实际上这里和时间没有关系,即使你改成0ms也是一样的结果。
那么,怎么让他按预期执行呢?不难发现i变量在回调函数内部没有被保存下来,那么我们就要想办法将其存下来,可以使用立即执行函数。
let's go~
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
我们这里使用了ES6新语法let,创建了一个块级作用域,使得变量i得以保存下来。
泰酷辣~块级作用域和闭包携手工作,解决世界上所有的问题。我不知道你怎么样,但这使我成了一个快乐的 JavaScript 开发者。