闭包初识

1.变量作用域

要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
看代码
  var n=999;
  function f1(){
    alert(n);
  }
  f1(); // 999
另一方面,在函数外部自然无法读取函数内的局部变量。
Js代码
  function f1(){
    var n=999;
  }
  alert(n); // error
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
Js代码
  function f1(){
    n=999;
  }
  f1();
  alert(n); // 999

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

出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
先看代码:
  function f1(){
    n=999;
    function f2(){
      alert(n); // 999
    }
  }
f2能访问到f1的变量
Javascript语言特有的“链式作用域”结构,子对象会一级一级地向上寻找所有父对象的变量。
所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!

再看:
function f1(){
       var  n=888;
        function f2(){
           alert(n)
        }
        return f2;
    }
    var result = f1();
    console.log(result)
结果:
//f2(){
            console.log(n)
        }
//然后在代码后再执行如下代码,
  result();//888,其实就是f2函数调用,
综合来看就是在函数体f1外边调用了函数的局部变量

3.深度理解

 var name = "The Window";   
  var object = {   
    name : "My Object",   
    getNameFunc : function(){   
      return function(){   
        return this.name;   
     };   
    }   
};   
alert(object.getNameFunc()());  //The Window
解析:object.getNameFunc()得到的结果是内部的function,然后在自执行,此时this指向window

再看:

function outerFun()
{
 var a =1;
 alert(a);  
}
var a=3;
outerFun();
alert(a);
结果是 ?? .  
再看下面的代码:

function outerFun()
{
 //没有var 
 a =1;
 alert(a);  
}
var a=4;
outerFun();
alert(a);
结果为??他们两次的结果不一样,真是奇怪,为什么呢?

4.两种形式

a)函数作为返回值
eg:
    function f1(){
        var a =100;
        function f2(){
            console.log(a)
        }
        return f2
    }

  f1()();//100

b)函数作为参数
eg:
var num = 10;
    var f2 = function (x) {
        x = x > num ? x : num;
        console.log(x)
    };
    (function(f){
        var num=50;
        f(30)
    })(f2)   //30
值得注意的是:代码运行,得到

      var num = 50;
      f2(30)//执行时取得是window下的num值,因为f2在window下创建的

自由变量跨作用域取值时:要去创建这个函数的作用域取值,而不是“父作用域”;

5.用处

eg:




var btns = document.getElementsByTagName("button");
    for(var i =0;i

6.总结

f1()调用完成。按理说应该销毁掉f1()的执行上下文环境,但是这里不能这么做,
因为执行f1()时,返回的是一个函数。函数的特别之处在于可以创建一个独立的作用域。
而正巧合的是,返回的这个函数体中,还有一个自由变量a要引用f1作用域下的f1()上下文环境中的a。
因此,这个max不能被销毁,销毁了之后f2函数中的a就找不到值了。

因此,这里的f1()上下文环境不能被销毁,还依然存在与执行上下文栈中。
eg:
 function f1(){
        var a =100;
        function f2(){
            console.log(a)
        }
        return f2
    }
    f1()()//100

[详情参考](http://www.cnblogs.com/wangfupeng1988/p/3994065.html);

闭包初识_第1张图片
image.png

你可能感兴趣的:(闭包初识)