闭包知识浅谈

什么是闭包?

闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

闭包要满足的条件:

【1】访问所在作用域;

【2】函数嵌套;

【3】在所在作用域外被调用

function func(){
  var n = 0;  // n是func函数的局部变量
  console.log(n,'func');//
  function closure() {  // closure是func函数的内部函数,是闭包
     n += 1;  // 内部使用了外部函数中的变量n
    console.log(n,'closure');
  }
  return closure;
}

var counter= func();//这里会调用一次func函数,打印  0,'func'

counter();  //调closure 打印 1,'closure'
counter();  //调closure 打印 2,'closure'
counter();  //调closure 打印 3,'closure'

闭包的特点:

让外部访问函数内部变量成为可能;

局部变量会常驻在内存中;

可以避免使用全局变量,防止全局变量污染;

会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

闭包的坑点:

坑点1:引用的变量可能已经发生变化

坑点2:this指向问题

坑点3:内存泄漏问题


经典案例:闭包与定时器

按照预期它应该依次输出1-10,而结果它输出了十次11,这是为什么呢?原来由于js是单线程的,所以在执行for循环的时候定时器setTimeout被安排到任务队列中排队等待执行,而在等待过程中for循环就已经在执行,等到setTimeout可以执行的时候,for循环已经结束,i的值也已经变成11,所以打印出来十个11,那么我们为了实现预期结果应该怎么改这段代码呢?(ps:如果把for循环里面的var变成let,也能实现预期结果)

引入闭包来保存变量i,将setTimeout放入立即执行函数中,将for循环中的循环值i作为参数传递,1秒后同时打印出1-10


闭包的应用:

给li添加点击事件,输出li对应的索引

<ul>
    <li>11111</li>
    <li>22222</li>
    <li>333333</li>
    <li>444444</li>
    <li>5555555</li>
</ul>
var list = document.querySelectorAll('li');
for (var i = 0; i < list.length; i++) {
    (function(i) { //var i=0-4
        list[i].onclick = function() {
            alert(i); //0-4
        }
    })(i);
}

猜你喜欢

转载自blog.csdn.net/qq_39264561/article/details/107522983
今日推荐