闭包认知的总结————终极版啦!

                             闭 包 翻 篇

前言:看了好多博客,每次都是当时看,过后就忘,理解的一点都不深刻,所以打算自己认真写一篇,先向参考的博客作者致敬。

         本文参考博客:
        1. http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html  

        2.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures (官方的)


第一步:理解链式作用域

答:Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。 不同于块级作用域哦!

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

如上,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的"链式作用域"结构(chain scope)子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

第二: 对于阮老师博客的理解补充

阮老师在闭包博客中说:它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中

第一点是认同的,但第二点有点不敢苟同(初生牛犊,如有错误,还请大神留言指教)。

阮老师的js代码:

function f1(){
    var n=999;
    nAdd=function(){n+=1}    //  全局变量
    function f2(){                     // 局部变量
      alert(n);
    }
    return f2;
  }

  var result=f1();      // 因为这里改变了f2的作用域,所以f2才一直在内存中。    作用域由(f1()内部变量 ——》f1()平级)。

  result();       // 999

  nAdd();       // 由结果看,下面的值为1000,说明nAdd() 执行了, 因为f2作用域被改变后就一直在内存中,所以f1也一直在内存中。

  result();      // 1000

    // 我如果这样写,换一种方式调用,不改变f2的作用域

      f1()(); // 999     执行完毕,f2的内存空间被销毁。 f1的内存空间也被销毁,nAdd虽然是全局变量,但其是方法的属性,自然也被销毁。

      nAdd();             // undefined     

      f1()();              // 还是999

由上面我们可以提出几点疑问:

1.注意变量的访问范围和生命周期

2.方法内部的全局变量会随着方法的销毁而销毁。     注意变量的访问范围生命周期!

3.第二种调用方式:立即执行函数。




一句话总结:

1.闭包就是能够读取其他函数内部变量的函数(是其他函数的内部函数)。

2.定义在一个函数内部的函数"。

3.闭包就是将函数内部和函数外部连接起来的一座桥梁。

4.由于js其特殊的作用域规则,要通过外部来访问函数的内部变量。 ——————闭包就是干这个的!

补充

代码理解:

function f1(){
var n=999;
nAdd=function(){n+=1;return n;} // 全局变量:都可以调用,前提是创建了-----销毁之前外部可以访问。
function f2(){
alert(n);
}
return f2;
}
alert(f1()); // 调用f1,返回f2 不调用f1都不会创建nAdd
alert(nAdd());
原文地址:https://www.cnblogs.com/njqa/p/6419854.html