图解JS中的闭包

127 阅读1分钟

经典的闭包代码

funciton foo(){
    var name = 'akechi'
    function bar(){
        console.log("bar",name)
    }
    return bar
}

var fn = foo()
fn() //akechi

开始解析代码的执行步骤

  • 首先初始全局执行上下文,编译foo函数和fn函数

  • 开始执行代码 编译foo函数内部代码

  • 执行foo函数的内部代码,返回bar函数对象的地址,赋值给fn函数

  • foo函数执行完毕,从ECStack挪出 (此时foo函数的ao对象没有被回收:因为bar函数父作用域指向它)

  • 执行fn函数,即执行bar函数

MDN闭包的定义

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment词法环境)的引用的组合

🚧🚧在例子中的体现就是bar函数和它可以访问name变量

闭包为何会导致内存泄漏?

正常的函数的AO对象在函数执行完成被弹出ECStack,失去引用后会被GC回收 但是闭包的AO对象始终被作用域指向着,所以不会被回收

闭包的作用

在实际编码中,闭包通常用来保存一些数据,或应用在高阶函数、柯里化中 举个常用的JS防抖的🌰

/*timer和_debounce函数就形成了闭包*/
function debounce(fn,delay){
	//1.定义一个定时器,保存上一次的定时器
	let timer = null
	//2.真正执行的函数
	const _debounce = function(...args){
		//取消上一次的定时器
		if(timer) clearTimeout(timer)
		timer = setTimeout(() => {
			//外部传入的真正要执行的函数
			//1.apply解决this指向问题 2.args解决event的传参问题
			fn.apply(this,args) 
		},delay)
	}

	return _debounce
}