js-closure

理解JavaScript闭包?

首先理解变量的作用域

变量的作用域无非两种

  • 全局变量 global
  • 局部变量 local

tips: 里提到一个小知识

使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象。
使用let声明的变量,其作用域为该语句所在的函数代码块内,不存在变量提升的现象
使用const声明的是常量,在后面出现的代码中不能再修改该常量的值
  1. 而JavaScript的语法中,函数内部可以直接读取全局变量

  2. 另一方面,函数外部自然无法读取函数内部的局部变量

  • 需要注意的是,函数内部声明变量的时候,一定要使用var命令,如果不用的话,你实际上是声明了一个全局变量
function f1(){
   n=999;
 }  
 f1();  
 alert(n); // 999

如何从外部读取局部变量?

由于项目需求,我们可能需要得到函数内的局部变量,但是在正常情况下这是做不到的。所以只能通过变通的方法实现。

在函数的内部再定义一个函数

function f1(){

     var n=999;

     function f2(){
       alert(n); // 999
     }

   }

上面是一个标准的JavaScript特有的 “链式作用域” 结构chain scope) ,子对象会一级一级的向父级对象寻找所有的变量

  • 既然f2可以读取到f1的变量,辣么,只要把f2作为返回值,我们不久可以再外部读取它的内部变量的吗?

    function f1(){
      var n=999;
      function f2(){
        alert(n); 
      }    
      return f2;
      }  
      var result=f1();
      result(); // 999
    

闭包的概念。

  1. f2 就是闭包
  2. 闭包:能读取其他函数内部(局部)变量的函数
  3. JavaScript中,只有函数内部的子函数能读取到局部变量,所以可以把闭包理解为:定义在函数内部的函数
  4. 闭包是函数内部以及外部链接的桥梁

闭包的作用?

  1. 可以读取函数内部的变量
  2. 让这些变量的值始终保持在内存中。
function f1(){
  var n=999;   
  nAdd=function(){
  n+=1
    }    
  function f2(){
      alert(n);
  }    
 return f2; 
 }  
var result=f1();  
result(); // 999 
nAdd();  
result(); // 10000

闭包的运行逻辑(个人理解,并不确定是否正确:路子野)

  1. function a(){ n = 1; function a1(){ console.log(“hello”)} return a1}
  2. b = a() c = a() //声明a函数 且赋值a()赋值于b,c变量
  3. 此时会再次生成两个内存空间存放b,c的闭包函数(a1)
  4. 由于a’.a1以及a’’.a1的存在也就是b,c的存在所以a’ 以及 a’’ 并不会被gc(辣鸡回收)
  5. 将内部变量保存在其中

注意

  1. 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

  2. 闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

  3. 调用你的是WHO?