javaScript 中的闭包

什么是闭包

在 js 中,有全局作用域和局部作用域,在局部作用域中可以访问全局作用域中的变量,反之则不行;在父级作用域中可以访问子级作用域中的变量,反之则不行。但有时,我们需要反向访问,该怎么办呢?这时,闭包应运而生。闭包,就是指能够访问其他函数内部变量的函数。

闭包的作用

  • 读取其他函数内部的变量
  • 让某些变量始终保持在内存中

例:

  function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }

  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000

上述代码中,nAdd 函数虽是在f1 函数内部初始化,但没有加关键词var ,所以 nAdd 是一个全局函数,可在外部调用;

f1 函数的执行结果,return 一个函数 f2,f2 函数在f1 函数的内部定义,可读取f1 函数中的变量,所以 f2 函数是一个闭包;

var result = f1() =>var result = f2 = function() { alert(n) },其中 n 是f1 的局部变量;

第一次执行 result() 时,直接打印出 n 的初始值 999;然后执行 nAdd() 函数,n 执行 +1 操作,n=1000;然后再次执行 result()操作,此时打印出的 n 是 +1 后的值,1000;

此例说明,n 的值始终保持在内存中,没有被销毁。

闭包的缺点

  • 由于闭包会让函数中的某些变量始终保持在内存中,所以不能大量使用,会很占用内存资源,造成网页卡顿崩溃;在IE中还可能导致内存泄漏
    • 解决方法:可在退出函数之前将不使用的局部变量删除;delete 可删除对象的属性;普通变量将其置为 undefined 或 null 即可
  • 闭包可以在 父函数的外部,改变其内部的值。如果将父函数当作对象使用,那其中的内部变量会有被修改的风险,具有一定的不稳定性

闭包的应用场景

  • setTimeout、setInterval 中的回调函数
  • ajax 中的回调函数
  • 函数内部 return 一个匿名函数,这个匿名函数就是闭包

经典例题

  var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
      };
    }
  };
  alert(object.getNameFunc()()); // The Window


  var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };
    }
  };
  alert(object.getNameFunc()()); // My Object
posted @ 2021-08-24 14:57  Upward123  阅读(31)  评论(0编辑  收藏  举报