前言
其实这篇文章算是我写的第一篇。因为之前的学习太混乱,导致很多东西掌握不牢,现在系统的学习并且把遇到的问题和个人的见解记录下来,方便自己复习,要是顺便能帮到大家就更好了。
能力不足,水平有限,如果写的有问题还希望大家指出问题,我好及时纠正。
JavaScript之闭包
概念
先举例,因为JavaScript的变量的读取是逐层向外查找的所以可以写出这样的代码:
function foo () {
var ark = 1;
return function bar () {
ark++;
console.log(ark);
}
}
var x = foo();
x(); // ark = 2
x(); // ark = 3
可以看出foo()这个函数中有一个局部变量ark = 1,并且返回了一个函数bar(),因为bar()是定义在foo()中的,所以可以访问变量ark,然后把foo()的返回值赋给变量x,这是x是个函数,接着调用x两次,可以发现ark本来是1,但是两次调用后ark在一直累加。其实这就是简单闭包。
个人理解就是一个函数可以访问一个自由变量就构成闭包了。
这里备注!如果变量ark定义在bar()中,foo()是不能访问的,而且如果你想要一个在函数中声明一个局部变量一定要var xxx = xxx!如果只是xxx = xxx,xxx会相当于一个全局变量。
从词法作用域理解为什么
但是上面闭包的例子成功的保存了ark这个变量,我的理解这个原因是因为,foo()中返回的函数bar()最后一次执行时foo()相当于还是在被间接的调用,所以foo()中的信息一直没有被销毁,而是存在内存中(所以个人觉得不能滥用)。这样ark的每次叠加就被记录了下来。
有什么用
目前我觉得闭包的用处就是可以对一个变量持续的操作,而这个变量不一定需要是全局变量(不用污染全局变量),比如在冴羽的博客中的跟着underscore学防抖这篇中有个需求是实现降低高频操作的频率,比如监听鼠标的移动,每次移动计数器加一,但是如果每次移动的操作很复杂,由于触发频率太高,可能就会有性能上的问题。那么我们可以使用setTimeout来延缓执行,如果这一次触发就重置这个定时器,这样在我们设置的毫秒数内就不会重复执行操作,引用这篇文章的例子理解闭包的用处。
function debounce(func, wait) {
var timeout;
return function () {
clearTimeout(timeout)
timeout = setTimeout(func, wait);
}
}
参数func是事件触发时要执行的方法,wait是等待的毫秒数。
为什么用闭包呢?因为如果在wait的时间内事件再一次被触发我们要clearTimeout,不这样的话只是把所有操作延后了一个wait而已,该执行多少次还是多少次,这就没有达成我们降低频率的要求,所以上一个timeout我们要给他保存下来,好在超过频率时给他清理掉,重新设置。这样我们就要对timeout持续操作,所以使用闭包。之后比较理解了高级用法的时候还会再来补充。
最后
如果有想深入理解的小伙伴可以去看看冴羽的博客。我觉得写的很好,很专业。要是大家有什么好的教程博客也可以推荐给我,我会十分感谢!