闭包
什么是闭包?JS最重要的部分之一就是闭包,最近又回过来复习基础的时候看见闭包了,以前也不是那么理解这东西,如果是自学的小白JS这部分看起来真的太费劲了,看的让人怀疑人生,看的怀疑自己是不是只有编程细菌。。。。好了废话不多说了,再细讲闭包之前呢,咋们先看个例子!!!
例:给三个button分别添加事件,点击的时候显示出点击的是第几个button???
乍一看是不是觉得很简单?那就开始写吧
思路是这样的没错吧,想要让每个按钮都有事件用for循环给每个button添加事件然后保存,可是事与愿违啊,真的是这样的吗???
这是最后的测试结果,第三个我没点击不用想了也是这个结果,惊大呆,这是为什么呢???
其实吧这个时候就构成了闭包,首先分析一下为什么点击每个按钮都显示的是点击了第三个按钮呢?这是因为每循环一次给btnList添加一个function,最后btnList是这样的 btnList[function(){},function(){},function(){}],里面有3个function,在for里面声明了function,但是它没有执行啊是不是?真正执行的时候是当你点击button的时候才执行这个函数啊,当你的行的时候bt已经变成3了,所以每触发一次事件都访问的是等于3的bt,所以每次访问都是3,先将闭包然后再用闭包来解这道题!!
闭包通俗点来说就是在外面能访问到局部变量,想想该怎么访问呢?
function father(){
var m=0;
return function child(){
console.log(m);
}
}
var ch=father();
ch();
结果输出就是0;而其中的child就是闭包,通常的闭包就长这样。。。在一个函数的内部再定义一个函数十有八九会产生闭包,不要把闭包想的那么复杂,说了半天就是让在函数外面访问函数内部的变量,它算是一座桥吧!!!
行,现在可以解决那个问题了,那就是把里面的onclick函数放在立即执行函数里,???什么是立即执行函数???从字面意思理解就是马上执行,完了就完了。。。
var bt1;
var btnList=document.getElementsByTagName("button");
for(var bt = 0;bt < btnList.length;bt ++){
(function(bt1){
btnList[bt1].οnclick=function(){
alert("您点击了第"+(bt1+1)+"个按钮");
}
})(bt)
}
当当当,就是它,把onclick这个函数放进立即执行函数里面就可以了,为什么可以呢,解释一下。。。因为当它执行for循环的时候每循环一次把bt送给bt1然后保留,执行完这个歌立即执行函数后销毁,再次执行的时候又是下一个值,所以最后拿出来的是你每循环一次的那个值而不是前面所说的执行到最后的那个值,执行函数是个好东西啊,它可以避免变量名的冲突,在一个立即执行函数里随便定义变量,只要出了这个作用域就没这个变量了,是不是美滋滋!!!补充一点,如果学习过ES6的话那个东西还可以那样写,不用闭包,那就是把for循环中的 var bt=0;中的var改成ES6中的 let 其实和立即执行函数差不多,都是作用域的问题!!!
说到这呢,大概对它有一定的了解了,可是知道了闭包什么时候用呢???只知道它是干嘛的不知道怎么用那不是白瞎吗?其实我觉得吧什么时候用的多呢?就是在模块化开发的时候,假如开发的时候需要有一个专门计算的模块,这个时候总不能使用全局变量吧,假如在外面调用这个模块,它直接返回计算值,这个时候就只能用闭包了!
不过吧,前面所说的那个return child()这个东西吧即在father的内部又在全局里面,所以啊它的那个变量会一直存在而不会被销毁,好多人都说闭包会引起内存的泄漏,但是吧,我觉得有时候有些开发必须得用闭包,是会引起内存泄漏,但是合理的利用就不会那么严重!下面谈谈内存泄漏吧
内存泄漏
就这个名词以前我第一次看的时候硬是没想通人家的内存泄漏到底是什么鬼?漏了?还是怎么回事???最近复习的时候我又好好的研究了一下这个名词,说了半天就是可用的内存泄露了,能用的就少了,是可用的泄露了。。。。大概就这么个意思吧,说起内存泄漏又会牵扯到这个垃圾回收的问题,过两天我总结一下然后写一份自己对垃圾回收的博客,今天就简单的说说内存泄漏怎么解决吧,就是把那些不需要的变量,但是垃圾回收又收不走的的那些赋值为null,然后让垃圾回收收走!!!