闭包是什么?有和特性?有何影响?

295 阅读2分钟
「这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战

闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,创建的函数可以访问到当前函数的局部变量。

闭包有两个常用的用途。

  • 闭包的第一个用途是使我们在函数外部能够访问到函数内部的变量。通过使用闭包,我们可以通过在外部调用闭包函数,从而在外部访问到函数内部的变量,可以使用这种方法来创建私有变量。

  • 函数的另一个用途是使已经运行结束的函数上下文中的变量对象继续留在内存中,因为闭包函数保留了这个变量对象的引用,所以这个变量对象不会被回收。

其实闭包的本质就是作用域链的一个特殊的应用,只要了解了作用域链的创建过程,就能够理解闭包的实现原理。

使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念

闭包有三个特性:

  1. 函数嵌套函数
  2. 函数内部可以引用外部的参数和变量
  3. 参数和变量不会被F垃圾回收机制回收
  • 作用域和自由变量
    • 自由变量查找:在函数定义的地方(而非执行的地方)
  • 闭包应用场景
    • 作为参数被传入
    • 作为返回值被返回
  • 闭包的影响
    • 变量会常驻内存,得不到释放
// 自由变量示例 -- 内存会被释放
let a =0 
function fn1(){
	let a1 =100
	function fn2(){
		let a2= 200
		function fn3(){
			let a3 = 300
			return a +a1+a2+a3
		}
		fn3()
	}
	fn2()
}
fn1()

// 闭包 函数作为返回值--内存不会被释放
function create(){
	let a =100 //被下面函数引用,不能释放
	return function(){
		console.log(a) 
	}
}
let fn =create()
let a  =200 //没被引用,可被释放
fn() // 100

// 闭包 函数作为传入值--内存不会被释放
function print(fn){
	let a =200 //没被引用,执行完成就可释放
	fn()
}
let a =100 // 被fn引用,不能释放
function fn(){
	console.log(a)
}
print(fn) // 100

常见闭包使用场景

间隔1s打印1-5

for (var i=1; i<=5; i++) {
  //闭包
  (function (i) {
    setTimeout(() => console.log(i), 1000*i)
  })(i)
}