合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
## 闭包 - 函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行 -- 这时候就产生了闭包 1. **父级函数的执行上下文环境无法释放,可以间接访问函数内部的变量。** 2. 占用更多的内存 3. 使用完闭包后需主动释放 ## 从执行上下文的角度理解闭包 ``` function foo() { var myName = "极客时间" let test1 = 1 const test2 = 2 var innerBar = { getName:function(){ console.log(test1) return myName }, setName:function(newName){ myName = newName } } return innerBar } var bar = foo() bar.setName("极客邦") bar.getName() console.log(bar.getName()) ``` * foo 函数的执行上下文如下 ![](https://img.kancloud.cn/2f/32/2f32f9186e429635817f0bc73b0de0ed_1142x660.png) * 当执行 var bar = foo() 后,foo函数执行完毕,执行上下文释放,虽然函数执行完毕,但是 getName 和 setName 对 myName 和 test1有引用,所以执行上下文变成这样: ![](https://img.kancloud.cn/f7/3b/f73b6e2029e4d2f95e761b3c2b48436a_1142x607.png) * 内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包 🌰 ``` var count = 10; function a() { return count + 10; } function b() { var count = 20; // function a() { // return count + 10; // } return a(); } console.log(b()); ``` **注意:函数的作用域是在函数定义和声明的时候确定的** 之所以形成闭包是因为函数 a 在声明的时候,他拥有覆盖 b() 的内部作用域 🌰 ``` for (var i = 0; i <= 5; i++) { setTimeout(() => { console.log(i) // 6 }, i * 1000); } console.log(i) // 6 在全局作用域中 ``` 1. 为什么会输出6呢? 因为在循环中,虽然每个函数是分别定义的,**但是变量i 是在全局作用域中的**,所以实际上只有一个 i 2. 如何改造 通过 IIFE 立即执行函数,为每个迭代都创建一个闭包, 但是需要让立即执行函数的**作用域不为空** ``` for (var i = 0; i <= 5; i++) { (function () { var j = i // 拥有自己的作用域 setTimeout(() => { console.log(j) }, j * 1000); })() } ```