• 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). 闭包在父函数外面,可以改变父函数内部的变量,如果将父函数作为对象,闭包作为公共方法,变量为私有属性,这是要注意不要随便改变父函数中的变量

  • 相关阅读:
    c# 扩展方法奇思妙用高级篇八:Type类扩展
    Asp.Net 上传大文件专题
    波形捕捉:(2)创建捕捉设备对象
    Capturing Waveforms【译】
    波形捕捉:(1)枚举"捕捉设备"
    C# 调用sql 2000存储过程
    HTTP请求流程(一)流程简介
    Asp.Net 上传大文件专题(4)利用ajax技术显示上传进度
    c# GDI+简单绘图(四)
    波形捕捉:(5)“捕捉缓冲区”信息
  • 原文地址:https://www.cnblogs.com/learning-skills/p/7645077.html
Copyright © 2020-2023  润新知