js闭包及解决办法:(内存泄漏-异步执行函数)

一:js闭包及解决办法

闭包在JavaScript高级程序设计(第3版)中是这样描述:闭包是指有权访问另一个函数作用域中的变量的函数。
闭包的作用:

1.访问其他函数内部变量

2.保护变量不被内存回收机制回收

3.避免全局变量被污染 方便调用上下文的局部变量 加强封装性

缺点:闭包会保存函数中的变量在内存中,导致内存消耗大,可能会造成内存泄漏

什么是内存泄漏
首先,需要了解浏览器自身的内存回收机制。
每个浏览器会有自己的一套回收机制,当分配出去的内存不使用的时候便会回收;内存泄露的根本原因就是你的代码中分配了一些‘顽固的’内存,浏览器无法进行回收,如果这些’顽固的’内存还在一直不停地分配就会导致后面所用内存不足,造成泄露。

function a(){
    var m = 2;
    function b(){
	   alert(m);
	}
	return b;
}
let func=a();
func()   // 2

问题1、内存泄漏

如何避免闭包引起的内存泄漏
1,在退出函数之前,将不使用的局部变量全部删除或者变量赋值为null.
2,避免变量的循环赋值和引用。

  这段代码会导致内存泄露
     function(){
        var a = document.getElementById("id");
       a.onclick = function(){
            alert(a.id);
        }
    }
    解决方法为
  function(){
        var a = document.getElementById("id");
        var id = a.id;                                      //解除循环引用
        a.onclick = function(){
            alert(id); 
        }
        a = null;                                          // 将闭包引用的外部函数中活动对象清除
    }

问题2、闭包与异步执行函数

前端使用异步执行的情况有
a 定时任务:setTimeOut() setInterval()
b 网络请求:ajax请求 动态加载
c 时间绑定

当遇到异步的情况时,函数的输出结果:

for(var i = 1; i <= 5;i++){

      setTimeout(function timer(){
        console.log( i );
      },i * 1000);


    } //输出结果是6 6 6 6 6 6

当执行setTimeOut()时,会暂时跳过这一段,放在缓冲区,当for循环执行结束之后,由于i是全局变量,此时在执行console.log( i )就会是 6,而不是预期中的0 1 2 3 4 5,解决办法通常有两种一是使用ES6中let使for循环中的变量变成块儿作用域,二就是使用立即执行函数,通过函数作用域可以保存变量的特性来将每次循环的变量 i 保存到函数中。

 使用let:

    for( let i = 0; i <= 5; i++){

      setTimeout( function timer(){

        console.log( i );

      },i * 1000);

    }// 输出结果 0 1 2 3 4 5

  使用立即执行函数(IIFE)

    for(var i = 0; i <= 5; i++){

      (function(){

        var j = i;

        setTimeout( function timer(){

          console.log( j );

        }, j * 1000);

      })();

    }//输出结果0 1 2 3 4 5

你可能感兴趣的:(前端知识点杂谈)