JavaScript中的函数会造成闭包。 闭包是由函数以及建立该函数的词法环境组合而成。这个环境包含了这个闭包建立时所能访问的全部局部变量。(闭包就是可以读取其余函数内部变量的函数。在本质上,闭包就是将函数内部和函数外部链接起来的一座桥梁。)javascript
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
}
console.log(new Date, i);
/* 结果:第 1 个 5 直接输出,1 秒以后,输出 5 个 5 Tue Mar 26 2019 11:25:19 GMT+0800 (中国标准时间) 5 Tue Mar 26 2019 11:25:20 GMT+0800 (中国标准时间) 5 Tue Mar 26 2019 11:25:20 GMT+0800 (中国标准时间) 5 Tue Mar 26 2019 11:25:20 GMT+0800 (中国标准时间) 5 Tue Mar 26 2019 11:25:20 GMT+0800 (中国标准时间) 5 Tue Mar 26 2019 11:25:20 GMT+0800 (中国标准时间) 5 */
// 若是指望代码的输出变成:5 -> 0,1,2,3,4 改造方法
1. 方案1: 匿名函数
for (var i = 0; i < 5; i++) {
(function(j) { // j = i
setTimeout(function() {
console.log(new Date, j);
}, 1000);
})(i);
}
console.log(new Date, i);
2. 方案2: 块级做用域
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(new Date, i);
}, 1000);
}
复制代码
闭包会使得函数中的变量都被保存在内存中,内存消耗很大,因此不能滥用闭包,不然会形成网页的性能问题,在IE中可能致使内存泄露。解决方法是,在退出函数以前,将不使用的局部变量所有删除。html
在requireJS出现以前,实现模块化编程主要经过IIFE,而在IIFE中常见的操做就是经过window.fn = fn来暴露接口,而这个fn就是闭包,而IIFE只是一个包含闭包的函数调用前端
(function(){
var a = 0;
function fn(){
console.log(a);
}
window.fn = fn;
})()
fn();
// 定义一:须要经过做用域链查找变量的函数就是闭包
var a = 2;
(function foo(){
console.log(a);//2
})();
// 定义二: 访问上层函数的做用域的内层函数就是闭包
function foo(){
var a = 2;
function bar(){
console.log(a); // 2
}
bar();
}
foo();
// 定义三: 在函数声明时的做用域之外的地方调用函数,须要经过将该函数做为返回值或者做为参数被传递
function foo(){
var a = 2;
function bar(){
console.log(a); //2
}
return bar;
}
foo()();
复制代码