zoukankan      html  css  js  c++  java
  • JS闭包、及闭包的应用场景

    闭包:如大家所知,通俗讲,可以访问其他函数内部变量的函数

    // 创建闭包最常见的方式函数作为返回值
    function fn() {
      let name = "小帆";
      return function() {
        console.log(name);
      };
    }
    let log = fn();
    log(); //打印“小帆”    --外部函数访问内部变量

    下面来实现一个简单的demo:计数器

    var number = 0;
    function creat() {
      number = number + 1;
      console.log(number );
    }
    creat(); //确实实现了需求

    //但是如果需要第二个计数器呢? //确定要像下面这样写吗? var num = 0; function creat_1() { num = num + 1; console.log(num ); } creat_1();

    如果我们需要的更多计数器,上面的写法就感觉代码很冗余了,这个时候可以考虑一下闭包:

    function createNum() {
      var number = 0;
      return function() {
        number = number + 1;
        console.log(number );
      };
    }
    
    var fun1 = createNum();
    fun1(); //1
    fun1(); //2
    var fun2 = createNum();
    fun2(); //1
    fun2(); //2

    有一种经典题目:for循环里的定时器引发的思考

    下面这道题的结果是多少?

    for (var i = 0; i < 4; i++) {
      setTimeout(function() {
        console.log(i);
      }, 300);
    }

    依次打印0,1,2,3  ???,然而打印的全都是4

    原因:JS 执行的时候首先会先执行主线程,异步相关的会存到异步队列里,当主线程执行完毕开始执行异步队列, 主线程执行完毕后,此时 i 的值为 4,说以在执行异步队列的时候,打印出来的都是 4(这里需要大家对 event loop 有所了解(js 的事件循环机制))

    要使其依次打印0,1,2,3,则可以考虑闭包:

    //方法一:
    //这个是通过自执行函数返回一个函数,然后在调用返回的函数去获取自执行函数内部的变量,此为闭包
    for (var i = 0; i < 4; i++) {
      setTimeout(
        (function(i) {
          return function() {
            console.log(i);
          };
        })(i),
        300
      );
    }
    
    //方法二:
    // 大部分都认为方法一和方法二都是闭包,我认为方法一是闭包,而方法二是通过创建一个自执行函数,使变量存在这个自执行函数的作用域里
    for (var i = 0; i < 4; i++) {
      (function(i) {
        setTimeout(function() {
          console.log(i);
        }, 300);
      })(i);
    }

    再举一个例子:获取多个元素并添加点击事件

    var op = document.querySelectorAll("p");
    for (var j = 0; j < op.length; j++) {
      op[j].onclick = function() {
        console.log(j);
      };
    }
    //log出来的值是一样的
    
    // 解决办法一:
    for (var j = 0; j < op.length; j++) {
      (function(j) {
        op[j].onclick = function() {
          alert(j);
        };
      })(j);
    }
    
    // 解决办法二:
    for (var j = 0; j < op.length; j++) {
      op[j].onclick = (function(j) {
        return function() {
          alert(j);
        };
      })(j);
    }

    既然这样,那每次遇到这种问题的时候我是不是可以都这样使用闭包?

    最后说一下,闭包有它的好处,也有它的坏处

    闭包的缺点:闭包会导致内存占用过高,因为变量都没有释放内存,从而垃圾回收机制不会销毁该变量。

  • 相关阅读:
    对TCP/IP协议的理解
    自己想到的几道Java面试题
    Java双重循环实现任意字符串中提取数字子串
    Spring data jpa 依赖配置
    spring data jpa sql
    spring boot 依赖配置
    Freemarker模板和依赖
    spring Data solr依赖文件 和xml配置文件
    根据mysql数据库 定义solr Schema.xml中配置业务域
    自定义solr域中的配置
  • 原文地址:https://www.cnblogs.com/btsn/p/13542342.html
Copyright © 2011-2022 走看看