javascript---闭包

1. 闭包

    有权访问另一个函数作用域中变量的函数,常见创建闭包的方式是在一个函数内部创建另一个函数。

2. 闭包原理

   先看看普通函数执行过程中,如何在作用域链查找变量的:

1 function compare(val1, val2) {
2    if(val1 < val2 ) {
3        return -1;  
4    }  else if (val1 > val2) {
5        return 1;
6    } else {
7        return 0;  
8    }
9 }
10 var result = compare(5,10);

  compare函数在执行过程中的作用域链:

    

  简单的闭包函数:

1 function createComparesionFunction(propertyName) {
2     return function(object1, object2) {
3         var val1 = object1[propertyName];
4         var val2 = object2[propertyName];
5         if(val1 < val2) {
6               return -1;
7           } else if (val1 > val2) {
8               return 1;
9           } else {
10               return 0;
11           }
12     }
13 }
14 var compareNames = createCompareFunction("name");
15 var result = compareNames({name: 'frank', name: 'jack'});
16 compareNames = null; (解除引用,释放内存)

注意: 由于闭包会包含它的函数的作用域,因此比其他函数占用内存要多,所以只有在必要的时候再使用

3. 闭包应用场景

   (1) 外部函数读取内部函数变量

 1 function f1() {
 2    var n =99;
 3    function f2() {
 4        alert(n);
 5    }
 6    return f2;
 7 }
 8 
 9 var result = f1();
10 result();//99

   (2) 将变量一直保存到内存中

 1 function f1() {
 2   var n = 99;
 3   nAdd = function() {n +=1};
 4   function f2 () {
 5     alert(n);
 6   }  
 7   return f2;
 8 }
 9 
10 var result = f1();
11 result();//99
12 nAdd();
13 result();//100

  分析: result是f2闭包函数, 调用两次闭包函数,第一次输出是99,第二次输出是100. 可以看出局部变量并没有因为f1()函数执行之后,而从内存中清除掉,而是一直保存在内存中。原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

 4. 使用闭包注意事项

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

   (2). 闭包在父函数外面,可以改变父函数内部的变量,如果将父函数作为对象,闭包作为公共方法,变量为私有属性,这是要注意不要随便改变父函数中的变量

原文地址:https://www.cnblogs.com/learning-skills/p/7645077.html