一.什么是闭包
在这之前讨论一下闭包的定义,不是说能够访问到其它作用域的变量就是闭包,这是很笼统的,闭包是基于正常的垃圾回收机制处理下的,也就是说,一般情况下在函数(函数作用域)执行完毕后,函数里面的变量会被全部释放出来,被垃圾回收机制给回收,但闭包用了一小技巧,也就是return 一个函数出去使用里面的变量,函数在执行完成后,里面的变量就不会被释放。
二.闭包的作用
作用: 延长变量的生命周期
解析:这里在调用fn() 函数后, 函数里面的变量num =10 ,一般会被释放, 但是里面有return
出fun()这个函数,给变量f,在fun函数里面打印了 变量num=10;也就是使用到了,此时不会被垃圾回收机制回收
三. 不是说能够访问到其它作用域的变量就是闭包,这是很笼统的;
代码1:
function fn(x) {
var num = 10
function fn1(y) {
console.log(x + y + num);//25
}
fn1(5)
}
fn(10)
解析: 首先要说明一点的是,这并不属于一个闭包,确实是访问到了另外一个作用域的变量,但是
并没有延长函数的生命周期,只是单纯地进行访问。 只是访问到了fn()函数里面的变量,很明显的一点是fn1函数只是在函数内部进行访问,而fn里面的变量根据作用域链查找规则:当一个函数内部的变量没有被访问到,就会去上级的函数进行查找。总而言之,它不属于闭包。
代码2:
function fn(x) {
var num = 10;
return function (y) {
console.log(x + num + y);
}
}
fn1 = fn(10)
fn1(5) //25
解析:之上方不同的是这次将 函数return出去了,并且在外部任然能访问到访问到fn()里面的变量,按照垃圾回收的机制来说:在函数执行完毕后,里面的变量将被释放,而此时外部的函数
fn1()能够访问到 fn()里面的变量, 证明了什么? 总结出来的一点是: 变量的生命周期延长; 因此才可以访问到,属于闭包的特点。
四.闭包的小案例
<button>按钮1</button>
<button>按钮2</button>
<button>按钮3</button>
<button>按钮4</button>
<script>
var btn = document.querySelectorAll('button')
for (var i = 0; i < btn.length; i++) {
btn[i].onclick = function () {
console.log('第' + i + '个按钮被点击了');
}
}
</script>
解析:不论你点击那个按钮,都会显示第4个按被点击了,具体的原因是点击事件是一个异步的任务,按钮还没有被点击,里面的 i就已经被执行完了,所以打印出去了永远是第四个。而我们的理想是,你点击那个按钮,就显示那个按钮被点击了。
代码:
var btn = document.querySelectorAll('button')
for (var i = 0; i < btn.length; i++) {
(function (i) {
btn[i].onclick = function () {
console.log('第' + i + '个按钮被点击了');
}
})(i)
}
使用立即执行函数把每次的循环的i 传入到里面函数里面,点击按钮触发时,进行打印。延长了变量的生命周期。
五. 总结出来一点闭包的主要作用是
延长了变量的生命周期。
新手小白,多多指点