不断积累和整理在JavaScript中常见的闭包问题,不断加深理解和学习运用:javascript
参考MDN网址:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closuresjava
闭包的官方定义: 闭包是由函数以及建立该函数的词法环境组合而成。这个环境包含了这个闭包建立时所能访问的全部局部变量(摘自MDN)浏览器
闭包的简单理解:但愿在另外一个做用域(好比在global中)访问局部做用域中的某个变量或函数闭包
(在谷歌浏览器中调试,发生闭包会有closure字样提示)异步
问题一:闭包的“雏形”:在全局做用域中访问某局部做用域中的变量或函数:函数
function fn() { var name = 'zs'; return function () { return name; } } var f = fn(); var n = f(); //或者这样写: var n= fn()(); console.log(n) //zs
问题二:用闭包解决在for循环中绑定事件的问题性能
假设不使用闭包解决这个问题,点击绑定的li的值输出的都是最后的一个值,由于触发点击事件的时候for循环已经结束了,且在for循环的做用域中 i 的值不断被覆盖学习
var list = document.getElementByTagName('li'); for (var i = 0 ;i < list.length ;i++){ var li = list[i]; ( function (index){ li.onclick = function(){ alert( index ); } })(i) }
自执行函数从全局做用域中访问for循环里面的 i, 给每一个 i 都新开创了一个做用域,让它保存i的值 spa
但过多的开创独立做用域,会形成额外的开销消耗性能,因此闭包有利有弊,像上面这种问题可使用let来解决调试
延伸:其余解决改问题的方法(使用let定义i)
var list = document.getElementByTagName('li'); for (let i = 0 ;i < list.length ;i++){ li.onclick = function(){ alert( i ); } }
问题三:用闭包解决在for循环中 setTimeout() 的问题
console.log(111) for ( var i = 0 ; i<3 ; i++){ setTimeout(function () { console.log(i) }, 0 ) } console.log(222) 最后的执行结果: 111 222 3 3 3
当js执行到setTimeout时会将其自动放入异步队列中去等待,直到主代码执行完后再去执行异步队列中的代码,因而3个3会在最后出现
使用闭包的方法避免这种状况:
console.log(111) for ( var i = 0 ; i<3 ; i++){ (function (index){ setTimeout(function () { console.log(i) }, 0 ) })(i) } console.log(222)
输出结果:
111
222
0
1
2
问题四:从闭包的角度给button等元素绑定事件demo
<a href="#" id="size-12">12</a> <a href="#" id="size-14">14</a> <a href="#" id="size-16">16</a>
function makeSizer(size) { return function() { document.body.style.fontSize = size + 'px'; }; } var size12 = makeSizer(12); var size14 = makeSizer(14); var size16 = makeSizer(16);
document.getElementById('size-12').onclick = size12; document.getElementById('size-14').onclick = size14; document.getElementById('size-16').onclick = size16;
size12
,size14
和 size16
三个函数将分别把 body
文本调整为 12,14,16 像素。咱们能够将它们分别添加到按钮的点击事件上。
总结:
上面是闭包的几个典型例子,除此以外闭包常见的问题还有用闭包模拟私有方法等等,同时要注意开创闭包后要给它赋值为null来清除,避免其常驻内存,形成内存泄漏等问题影响性能,固然还有其余方式。
闭包考量性能,既实用,同时也有弊端。
运用好闭包是掌握JS的重点之一。革命还没有成功,同志仍需努力!