JavaScript闭包


什么是闭包

MDN的解释是
函数与对其状态即词法环境的引用共同构成闭包。也就是说,闭包可以让你从内部函数访问外部函数作用域。在JavaScript,函数在每次创建时生成闭包。

闭包咋来的

自己简单总结下

  • 闭包的产生有三个条件
    • 要有一个内嵌函数,就是在函数 fn1 内部直接或间接返回了一个函数 fn2

    • fn2 函数内部必须引用着 fn1 函数的变量

    • fn1 函数返回的 fn2 函数要有外部变量接收

      • 形成了一个不会销毁的 fn1 函数的执行空间,我们管这个不会销毁的函数空间叫做 闭包空间
      • 把函数 fn1 里面返回的函数 fn2,叫做函数 fn1 的 闭包函数
  • 为什么这个函数空间不会被销毁?
    一个函数再执行的时候,会开辟一个函数执行空间,代码执行完毕之后,根据 js 垃圾回收机制,这个函数执行空间会被销毁。
    在一个特殊情况下,函数的这个执行空间不会被销毁。
    什么特殊情况?
    当函数内部返回一个复杂数据类型,并且在函数外部有变量接收这个复杂数据类型的时候,这个函数的执行空间就不会被销毁,即不会被垃圾回收机制回收。

垃圾回收机制:
在JavaScript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收机制回收;
如果两个对象互相引用,而不再被第三者所引用,那么这两个互相引用的对象也会被回收。

什么情况会被销毁?

当函数外部的变量不再引用函数内部的返回值时会被销毁。

看一个简单的应用闭包的例子

function a() {
	// 这个 num 变量是函数 a 的私有变量
	var num = 100
	return function b() {
	  console.log(num)
	}
}
// res 接受的就是函数 a 内部返回的一个复杂数据类型(函数b),导致函数 a 的执行空间不会销毁
var res = a()
res()	//打印100
//这样就做到了从函数 A 外部拿到函数 A 的 num

为啥要用闭包

闭包的优点

  1. 延长了变量的生命周期
  2. 可以访问函数内部的私有变量

闭包的缺点

  • 因为一段内存空间内的函数空间不会被销毁,在使用不当的情况下,容易发生内存泄漏 (致命的缺点)
    所以,如果闭包函数此时使用完毕之后,后面不再使用,应该另外部接收闭包函数的参数手动销毁

间接返回一个函数

直接返回一个函数就是 return function() {}
当我们需要访问多个私有数据时,就要用到间接返回的方式

function fn() {
	var num = 100
	var num2 = 200
	
	return {
		getNum: function () {
			console.log(num)
		},
		getNum2: function () {
			console.log(num2)
		}
	}
}
var res = fn()
// res 得到的是一个对象
// 这个对象里面的函数是 fn 的闭包函数
console.log(res)
res.getNum()  //100
res.getNum2()  //200

闭包能干啥

简单使用闭包函数

循环绑定事件

var btns = document.querySelectorAll('button')
function loop(num) {
	btns[num].onclick = function() {
		console.log(num)
	}
}
for (var i = 0; i < btns.length; i++) {
	loop(i)
}

实际上就是es6用let解决循环绑定事件的本质

for (let i = 0; i < btns.length; i++) {
	btns[i].onclick = function() {
		console.log(i)
	}
}

利用闭包实现单例模式

var Person = (function fn() {  //匿名自执行函数
	function Person() {  //真正的构造函数
		console.log('hello world')
	}
	
	var instance = null	//声明一个instance 对象
	return function() {
		return instance || (instance = new Person())
	}		//如果存在返回instance,如果不存在则new一个Person对象
})()

 var p1 = new Person()
 console.log(p1)
 var p2 = new Person()
 console.log(p2)
 console.log(p1 === p2)		//true

最后需要要注意!

因为闭包的缺点就是闭包函数常驻内存会增大内存使用量,而且使用不当很容易造成内存泄漏。
所以如果不是因为特殊情况而必须需要闭包,在没有必要的情况下,不要使用闭包!
闭包:慎用!!



关键字:JavaScript , 闭包 ,函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值