0%

闭包的深入理解

闭包的深入理解

分享原因:在逛博客的时候,看到了有关闭包的问题,不是特别理解,然后查找了相关的文章。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var n = 1;
function fun1() {
test = 10;    
var n = 999;    
nAdd = function() {
n += 1;
console.log(n);
}    
function fun2() {      
console.log(n);    
}    
return fun2;  
}
var result = fun1();
result();
console.log(test);
console.log(n);
nAdd();
result();

闭包是函数和声明该函数的词法环境的组合。

  1. 理解js变量的作用域

    访问规则:

    i) 函数内部可以直接读取全局变量

    1
    2
    3
    4
    5
    6
    7
         var n=999;

      function f1(){
        alert(n);
      }

      f1(); // 999

    ii) 在函数外部无法读取函数内的局部变量

    1
    2
    3
    4
    5
         function f1(){
        var n=999;
      }

      alert(n); // Uncaught ReferenceError: n is not defined

    iii) 内部函数可以访问外部函数的变量

    1
    2
    3
    4
    5
    6
    7
         function f1(){
        var n=999;
    (function f2(){
    alert(n);
    })();
      }
    f1();//999
  2. 如何实现从外部读取局部变量

    js链式作用域结构:父对象的所有变量,对子对象都是可见的,反之则不成立。

    1
    2
    3
    4
    5
    6
    7
    8
    9
         function fun1(){
        var n=999;
        function fun2(){
          alert(n);
        }
        return fun2;
      }
      var result=fun1();
      result(); // 999
  3. 闭包的概念

    理解上,闭包就是能够读取其他函数内部变量的函数,将函数内部和函数外部连接起来的一座桥梁;但是事实上闭包不是一个函数,而是函数和声明该函数的词法环境的组合,这个环境包含了这个闭包创建时所能访问的所有局部变量

  4. 闭包的用途

    产生条件

    1. 一个函数,里面有一些变量和另一个函数
    2. 外部函数里面的函数使用了外部函数的变量
    3. 外部函数最后把它里面的那个函数用return抛出去

    作用:

    • 在函数外部可以读取函数内部的变量
    • 让这些变量的值始终保持在内存中

    注意:

    • 由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,可能导致内存泄露。解决方法是,在退出函数之前,将不需要的局部变量赋值为null。
    • 闭包会在父函数外部改变父函数内部变量的值。如果你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时一定要注意,不要随便改变父函数内部变量的值。
    • 当定义一个函数时,它实际上保存一个作用域链。当调用这个函数时,它创建一个新的对象来存储它的局部变量,并将这个对象添加至保存的那个作用域链上,同时创建一个新的更长的表示函数调用作用域的“链”。对于嵌套函数来讲,每次调用外部函数时,内部函数又会重新定义一遍。因为每次调用外部函数的时候,作用域链都是不同的。内部函数在每次定义的时候都有微妙的差别——在每次调用外部函数时,内部函数的代码都是相同的,但是关联这段代码的作用域链不相同,用闭包概念来说,也就是产生了新的闭包。