JS 话题之一:闭包
闭包是一个内部函数。我记得刚开始面试的时候是这样子形容它的:闭包就是函数内的函数。回答可能不够完整,结合大神的理解,今天梳理一遍
闭包是一个内部函数,它可以访问外部函数的作用域链中的变量(可以访问全局变量,自身作用域的变量和封闭函数内的变量)。词法作用域、作用域链、垃圾回收机制,是由该函数与其上下文公狗构成的。
let globV = 'a';
(function(outA){
(function(innerA){
let innerV = 'b';
console.log(globV+"###"+outA+"###"+innerA+"###"+innerV)
//a ### 1 ### 2 ### b
})(2)
})(1)
例子
// 下面如果输出想要的1,2,3,4,5
for (var i = 0;i<5;i++){
// 此时定时器只会引用循环结束后的储存的i的值5
setTimeout(function(){console.log(i)},i*1000) //5 5 5 5 5
}
// 改1:通过每次迭代创建一个唯一的作用域,并将变量的唯一值存储在作用域中
for(var i= 0; i< 5;i++){
((x) => {
setTimeout(function () {
console.log(x) // 0 1 2 3 4
},1000)
})(i)
}
// 立即执行函数IIFE是以()为开始的
// 改2: 使用let:会隐形的创造块作用域,变量不会提升
for (let i = 0;i<5;i++){
setTimeout(function(){
//此时取值都是取得块作用域里面的i值
console.log(i)
},i*1000) //5 5 5 5 5
}
闭包会带来的弊端
a、内存泄漏 memory leak
闭包阻止了垃圾回收机制对变量进行回收,变量就会保存在内存中,影响页面的性能。
//释放变量
function fn(){
let a = 1;
function bar(){
console.log(a)
}
return bar;
}
let baz = fn(); //指向的对象会一直保存在堆内存中
baz = null; // 若不再使用,则让其指向的对象为空