• JavaScript中闭包的简单介绍


    1.什么是闭包

    《JavaScript高级程序设计》这样描述:

    闭包是指有权访问另一个函数作用域中的变量的函数;

    最常见的闭包结构如下

    function aaa(){
      var name = "xxx"
      return function bbb(){
        alert(name);
      }
    }
    

    如上代码,bbb函数内可以访问aaa函数作用域内的变量

    2.闭包的作用

    正常函数执行完毕后,里面声明的变量被垃圾回收处理掉,但是闭包可以让作用域里的 变量,在函数执行完之后依旧保持没有被垃圾回收处理掉

    3.闭包的特性

    外部的方法和变量就不会污染闭包内部的东西,同时,闭包内的变量也会有效的保存下来

    function person(name) {
        // 变量作用域为函数内部,外部无法访问,防止了变量名冲突和污染
        var name = '小明';
        this.sayName= function() {
            alert(name)
        }
        this.changeName= function(newName) {
            name = newName
        }
    }
    // 外部无法访问内部变量
    let a = new person()
    console.log(a.name) // undefiend
    a.changeName('小白')
    // 这里修改的name会保存下来
    a.sayName() // 小白
    

    4.闭包的实例

    返回函数

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

    常见的定时器问题

    for( var i = 0; i < 5; i++ ) {
        setTimeout(() => {
            console.log( i );
        }, 1000)
    }
    

    得到结果 5个5
    setTimeout函数在当前执行队列的最后执行,获取到的i是最外部作用域的i=5,所以得到5个5

    那么如果想1s后得到0-4怎么做?在for循环内创建闭包

    //方法一:
    for (var i = 0; i < 5; i++) {
      setTimeout(
        (function(i) {
          return function() {
            console.log(i);
          };
        })(i),
        1000
      );
    }
    // 或者
    for (var i = 0; i < 5; i++) {
      setTimeout(
        (function() {
          var temp = i;
          return function() {
            console.log(temp);
          };
        })(),
        1000
      );
    }
    //这个是通过自执行函数返回一个函数,然后在调用返回的函数去获取自执行函数内部的变量,此为闭包
    
    //方法二:
    for (var i = 0; i < 5; i++) {
      (function(i) {
        setTimeout(function() {
          console.log(i);
        }, 1000);
      })(i);
    }
    

    大部分都认为方法一和方法二都是闭包,我认为方法一是闭包,而方法二是通过创建一个自执行函数,使变量存在这个自执行函数的作用域里;

    此外,还可以通过将var改为let,这样for循环就拥有了块级作用域,也能解决这个问题;

    计数器

    接下来实现一个计数器大家肯定会觉得这不是很简单吗

    var count = 0;
    
    function add() {
      count = count + 1;
      console.log(count);
    }
    add(); //确实实现了需求
    //但是如果需要第二个计数器呢?
    //难道要如下这样写吗?
    var count1 = 0;
    
    function add1() {
      count1 = count1 + 1;
      console.log(count1);
    }
    add1(); //确实实现了需求
    

    当我们需要更多的时候,这样明显是不现实的,这里我们就需要用到闭包.

    function addCount() {
      var conut = 0;
      return function() {
        count = count + 1;
        console.log(count);
      };
    }
    

    这里解释一下上边的过程:

    • addCount() 执行的时候, 返回一个函数
    • 函数是可以创建自己的作用域的, 但是此时返回的这个函数内部需要引用 addCount() 作用域下的变量 count, 因此这个 count 是不能被销毁的
    • 接下来需要几个计数器我们就定义几个变量就可以,并且他们都不会互相影响,每个函数作用域中还会保存 count 变量不被销毁,进行不断的累加
    var fun1 = addCount();
    fun1(); //1
    fun1(); //2
    var fun2 = addCount();
    fun2(); //1
    fun2(); //2
    

    5.注意事项

    由于闭包会常驻内存,使用不当会导致内存溢出。

  • 相关阅读:
    对于进程的理解
    反汇编引擎实现——流程分析
    window异常处理——except_handler4以及栈展开分析
    对于硬盘驱动的理解
    对文件系统的理解
    移动端适配flexible.js
    vue学习(5)-评论功能(利用父组件的方法)
    vue学习(4)-组件的创建,父子组件传值,$refs
    vue学习(3)-增删改查
    vue学习(2)-过滤器
  • 原文地址:https://www.cnblogs.com/AhuntSun-blog/p/13644230.html
Copyright © 2020-2023  润新知