闭包和立即执行函数

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

function a(){
    var n = 0;
    function inc() {
        n++;
        console.log(n);
    }
    inc();  
    inc(); 
}
a(); //控制台输出1,再输出2

function a(){

    var n = 0;

    this.inc = function () {

        n++;

        console.log(n);

    };

}

var c = new a();

c.inc();    //控制台输出1

c.inc();    //控制台输出2

function a(){
    var n = 0;
    function inc(){
       n++; 
       console.log(n);
    }
    return inc;
}
var c = a();
c();    //控制台输出1
c();    //控制台输出2
var c1 = a();
c1();    //控制台输出1
c1();    //控制台输出2

闭包陷阱:

function createFunctions(){
    var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(){
            return i;
        };
    }
    return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
    console.log(funcs[i]());
}

乍一看,以为输出 0~9 ,万万没想到输出10个10? 

解决闭包问题:

function createFunctions() {

    var result = new Array();

    for (var i = 0; i < 10; i++) {

        (function(i) {//添加一个立即执行的函数

            result[i] = function() {

                return i;

            };

        })(i);

    }

    return result;

}

var funcs = createFunctions();

for (var i = 0; i < funcs.length; i++) {

    console.log(funcs[i]());

}

var result = new Array(), i;
result[0] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
result[1] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
...
result[9] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
i = 10;
funcs = result;
result = null;
 
console.log(i); // funcs[0]()就是执行 return i 语句,就是返回10
console.log(i); // funcs[1]()就是执行 return i 语句,就是返回10
...
console.log(i); // funcs[9]()就是执行 return i 语句,就是返回10

 function f1(){

    n=999;

    function f2(){

      return (n); // 999

    };

return f2;

};

f1()();

//控制台输出999

立即执行函数:

 (function f1(){

    n=999;

    function f2(){

      return (n); // 999

    };return f2;

  })();

//控制台输出

function f2(){

   return (n); // 999

 }

 (function f1(){

    n=999;

    function f2(){

      return (n); // 999

    };return f2;

  })()();

//控制台输出

999

 (function f1(){

    n=999;

    function f2(){

      return (n); // 999

    };return f2;

  }())();

//控制台输出

999

function f1(){

    var n=999;

    nAdd=function(){n+=1}

    function f2(){

      alert(n);

    }

    return f2;

  }

  var result=f1();

  result(); // 999

  nAdd();

  result(); // 1000

在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

使用闭包的注意点

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

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

 

内存泄漏也称作"存储渗漏",用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。

var name = "The Window";  

var object = {    

    name: "My Object",

        getNameFunc: function() {      

        return function() {        

            return this.name;     

        };    

    }

};

alert(object.getNameFunc()()); //The Window

//控制台输出The Window

function outerFun() {

    var a = 0;

    console.log(a);

}

var a = 4;

outerFun();

console.log(a);

//控制台输出0,4

作用域链

function outerFun() {

    //没有var

    a = 0;

    alert(a);

}

var a = 4;

outerFun();

alert(a);

结果为 0, 0 真是奇怪, 为什么呢 ?

    作用域链是描述一种路径的术语, 沿着该路径可以确定变量的值。 当执行a = 0时, 因为没有使用var关键字, 因此赋值操作会沿着作用域链到var a = 4;

并改变其值。

原文地址:https://www.cnblogs.com/songjn/p/9469803.html