Day23:继续闭包的故事

【书名】:你不知道的JavaScript(上卷)

【作者】:Kyle Simpson

【本书总页码】:213

【已读页码】:63

function\ wait(message)\ \left\{\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\         setTimeout( function\ timer()\ \left\{\\             console.log( message );\ \ \ \ \ \ \\ \right\},\ 1000 );\right\}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\\ \\wait(

将一个内部函数(名为 timer)传递给 setTimeout(..)。timer 具有涵盖 wait(..) 作用域的闭包,因此还保有对变量 message 的引用。

wait(..) 执行 1000 毫秒后,它的内部作用域并不会消失,timer 函数依然保有 wait(..)作用域的闭包。

深入到引擎的内部原理中,内置的工具函数 setTimeout(..) 持有对一个参数的引用,这个参数也许叫作 fn 或者 func,或者其他类似的名字。引擎会调用这个函数,在例子中就是内部的 timer 函数,而词法作用域在这个过程中保持完整。

这就是闭包。

本质上无论何时何地,如果将函数(访问它们各自的词法作用域)当作第一级的值类型并到处传递,你就会看到闭包在这些函数中的应用。在定时器、事件监听器、Ajax 请求、跨窗口通信、Web Workers 或者任何其他的异步(或者同步)任务中,只要使用了回调函数,实际上就是在使用闭包!

var a = 2;\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \\\ \\(function\ IIFE()\ \left\{\\console.log( a );\\\right\})();\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \

虽然这段代码可以正常工作,但严格来讲它并不是闭包。因为函数IIFE并不是在它本身的词法作用域以外执行的。它在定义时所在的作用域中执行(而外部作用域,也就是全局作用域也持有 a)。a 是通过普通的词法作用域查找而非闭包被发现的。

尽管 IIFE 本身并不是观察闭包的恰当例子,但它的确创建了闭包,并且也是最常用来创建可以被封闭起来的闭包的工具。因此 IIFE 的确同闭包息息相关,即使本身并不会真的使用闭包。

你可能感兴趣的:(Day23:继续闭包的故事)