JavaScript作用域和闭包( 二 )



JavaScript作用域和闭包

文章插图

10因为闭包可以访问外层函数的变量 , 因此他们通常有两种用途:
减少副作用
创建私有变量
使用闭包控制副作用
当你在函数返回值时执行某些操作时 , 通常会发生一些副作用 。 副作用在很多情况下都会发生 , 比如Ajax调用 , 超时处理 , 或者哪怕是console.log的输出语句:

JavaScript作用域和闭包

文章插图

11当使用闭包来控制副作用时 , 实际上是需要考虑哪些可能会混淆代码工作流程的部分 , 比如Ajax或者超时 。
要把事情说清楚 , 还是看例子比较方便:
比如说你要给为你朋友庆生 , 做一个蛋糕 。 做这个蛋糕可能花1秒钟的时间 , 所以写了一个函数记录在一秒钟以后 , 记录做完蛋糕这件事 。
为了让代码简短易读 , 使用了ES6的箭头函数:

JavaScript作用域和闭包

文章插图

12但这里的问题是 , 并不想立刻知道蛋糕的味道 。 只需要知道时间到了 , 蛋糕做好了就行 。
要解决这个问题 , 可以写一个prepareCake的功能 , 保存蛋糕的口味 。 然后 , 在返回在内部调用prepareCake的闭包makeCake 。
从这里开始 , 就可以在你需要的时调用 , 蛋糕也会在一秒后立刻做好 。

JavaScript作用域和闭包

文章插图

13这就是使用闭包减少副作用:可以创建一个任你驱使的内层闭包 。
私有变量和闭包
前面已经说过 , 函数内的变量 , 在函数外部是不能访问的既然不能访问 , 那tc 就可以称作私有变量 。
确实是需要访问私有变量的 。 这时候就需要闭包的帮助了 。

JavaScript作用域和闭包

文章插图

14这个例子里的saySecretCode函数 , 就在原函数外暴露了secretCode这一变量 。 因此 , 它也被成为特权函数 。
使用DevTools调试
Chrome和Firefox的开发者工具都能很方便的调试在当前作用域内可以访问的各种变量一般有两种方法 。
第一种方法是在代码里使用debugger关键词 。 这能让浏览器里运行的JavaScript的暂停 , 以便调试 。
下面是prepareCake的例子:

JavaScript作用域和闭包

文章插图

15打开Chrome的开发者工具 , 定位到Source页下(或者是Firefox的Debugger页) , 你就能看到可以访问的变量了 。

JavaScript作用域和闭包

文章插图

16使用debugger调试prepareCake的作用域 。
也可以把debugger关键词放在闭包内部 。 注意对比变量的作用域:

JavaScript作用域和闭包

文章插图

17通过断点调试作用域
闭包和作用域并不是那么难懂 。 一旦使用双向镜的思维去理解 。
在函数里声明一个变量时 , 只能在函数内访问 。 这些变量的作用域就被限制在函数里了 。
如果你在一个函数内又定义了内部函数 , 那么这个内部函数就被称作闭包 。 它仍可以访问外部函数的作用域 。

推荐阅读