不断更新:整理常见的闭包问题

不断积累和整理在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;

size12size14 和 size16 三个函数将分别把 body 文本调整为 12,14,16 像素。咱们能够将它们分别添加到按钮的点击事件上。

总结:

 上面是闭包的几个典型例子,除此以外闭包常见的问题还有用闭包模拟私有方法等等,同时要注意开创闭包后要给它赋值为null来清除,避免其常驻内存,形成内存泄漏等问题影响性能,固然还有其余方式。

闭包考量性能,既实用,同时也有弊端。

运用好闭包是掌握JS的重点之一。革命还没有成功,同志仍需努力!

相关文章
相关标签/搜索