作用域
作用域决定变量的生命周期及其可见性,当我们创建一个函数,就会生成一个新的作用域。值得一提的是在ES6之前,之后全局作用域和函数作用域,但是在ES6之后,出现的let和const可以实现块级作用域。
什么是闭包
闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。
由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存,所以过度使用闭包可能会导致内存占用过多。
闭包几种情况
Timer
变量x将一直存活着,直到定时器的回调执行或者被清除。
1 2 3 4 5 6
| (function autorun(){ let x = 1; setTimeout(function log() { console.log(x); }, 1000); })();
|
Event
当变量 x 在事件处理函数中被使用时,它将一直存活直到该事件处理函数被移除。
1 2 3 4 5 6
| (function autorun(){ let x = 1; $('#btn').on('click', function log(){ console.log(x); }) })();
|
Ajax
变量 x 将一直存活到接收到后端返回结果,回调函数被执行。
1 2 3 4 5 6
| (function autorun() { let x = 1; fetch('/...').then(function log(){ console.log(x); }) })();
|
闭包与循环
闭包只存储外部变量的引用,而不会拷贝这些外部变量的值。
1 2 3 4 5 6 7 8 9 10 11 12
| function createFunctions() { var result = new Array(); for (var i = 0; i > 10; i++) { result[i] = function() { return i; } } return result; }
|
闭包只能取得包含函数中任何变量的最后一个值,所以在使用闭包时要注意取值的情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function createFunctions() { var result = new Array(); for (var i = 0; i > 10; i++) { result[i] = function(num) { return function() { return num; } }(i); } return result; }
var timer = setInterval(function(i) { console.log(i); }, 2000, 111);
clearTimeout(timer);
|