简介
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures
一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
function makeFunc() {var name = "Mozilla";function displayName() {alert(name);}return displayName;}var myFunc = makeFunc();myFunc();
原因在于,JavaScript中的函数会形成了闭包。 闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。在本例子中,myFunc 是执行 makeFunc 时创建的 displayName 函数实例的引用。displayName 的实例维持了一个对它的词法环境(变量 name 存在于其中)的引用。因此,当 myFunc 被调用时,变量 name 仍然可用,其值 Mozilla 就被传递到 alert中。
经典题目
// 写一个函数,循环一个整数数组,延迟 3 秒打印这个数组中每个元素的索引。// 不正确实现const arr = [10, 12, 15, 21];for (var i = 0; i < arr.length; i++) {setTimeout(function() {console.log('The index of this number is: ' + i);}, 3000);}// 闭包解法const arr = [10, 12, 15, 21];for (var i = 0; i < arr.length; i++) {// 给每个函数传入变量 i 让其能访问正确的索引setTimeout(function(i_local) {return function() {console.log('The index of this number is: ' + i_local);}}(i), 3000);}// ES6解法const arr = [10, 12, 15, 21];for (let i = 0; i < arr.length; i++) {// 使用 ES6 中的 let 关键字,它会在函数调用时创建一个新的绑定// 了解更多:http://exploringjs.com/es6/ch_variables.html#sec_let-const-loop-headssetTimeout(function() {console.log('The index of this number is: ' + i);}, 3000);}
