`
这些年
  • 浏览: 401795 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

闭包(转)

    博客分类:
  • js
 
阅读更多

 

 
1,闭包外层是个函数.
2,闭包内部都有函数.
3,闭包会return内部函数.
4,闭包返回的函数内部不能有return.(因为这样就真的结束了)
5,执行闭包后,闭包内部变量会存在,而闭包内部函数的内部变量不会存在.

闭包的应用场景(呵呵,复制的参考资料)
1、保护函数内的变量安全。以最开始的例子为例,函数a中i只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
2、在内存中维持一个变量。依然如前例,由于闭包,函数a中i的一直存在于内存中,因此每次执行c(),都会给i自加1。

 

我们来看看闭包的用途。事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。


1 匿名自执行函数


我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处,
比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。
除了每次使用变量都是用var关键字外,我们在实际情况下经常遇到这样一种情况,即有的函数只需要执行一次,其内部变量无需维护,
比如UI的初始化,那么我们可以使用闭包:

 

[javascript] view plaincopyprint?
  1. var datamodel = {    
  2.     table : [],    
  3.     tree : {}    
  4. };    
  5.      
  6. (function(dm){    
  7.     for(var i = 0; i < dm.table.rows; i++){    
  8.        var row = dm.table.rows[i];    
  9.        for(var j = 0; j < row.cells; i++){    
  10.            drawCell(i, j);    
  11.        }    
  12.     }    
  13.        
  14.     //build dm.tree      
  15. })(datamodel);   

 

我们创建了一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,
因此在执行完后很快就会被释放,关键是这种机制不会污染全局对象。

2缓存


再来看一个例子,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,
那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,
然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,
从而函数内部的值可以得以保留。

 

[javascript] view plaincopyprint?
  1. var CachedSearchBox = (function(){    
  2.     var cache = {},    
  3.        count = [];    
  4.     return {    
  5.        attachSearchBox : function(dsid){    
  6.            if(dsid in cache){//如果结果在缓存中    
  7.               return cache[dsid];//直接返回缓存中的对象    
  8.            }    
  9.            var fsb = new uikit.webctrl.SearchBox(dsid);//新建    
  10.            cache[dsid] = fsb;//更新缓存    
  11.            if(count.length > 100){//保正缓存的大小<=100    
  12.               delete cache[count.shift()];    
  13.            }    
  14.            return fsb;          
  15.        },    
  16.      
  17.        clearSearchBox : function(dsid){    
  18.            if(dsid in cache){    
  19.               cache[dsid].clearSelection();      
  20.            }    
  21.        }    
  22.     };    
  23. })();    
  24.      
  25. CachedSearchBox.attachSearchBox("input1");    

 

这样,当我们第二次调用CachedSearchBox.attachSerachBox(“input1”)的时候,
我们就可以从缓存中取道该对象,而不用再去创建一个新的searchbox对象。

3 实现封装


可以先来看一个关于封装的例子,在person之外的地方无法访问其内部的变量,而通过提供闭包的形式来访问:

 

[javascript] view plaincopyprint?
  1. var person = function(){    
  2.     //变量作用域为函数内部,外部无法访问    
  3.     var name = "default";       
  4.        
  5.     return {    
  6.        getName : function(){    
  7.            return name;    
  8.        },    
  9.        setName : function(newName){    
  10.            name = newName;    
  11.        }    
  12.     }    
  13. }();    
  14.      
  15. print(person.name);//直接访问,结果为undefined    
  16. print(person.getName());    
  17. person.setName("abruzzi");    
  18. print(person.getName());    
  19.    
  20. 得到结果如下:  
  21.    
  22. undefined  
  23. default  
  24. abruzzi  

 

 

4 闭包的另一个重要用途是实现面向对象中的对象,传统的对象语言都提供类的模板机制,
这样不同的对象(类的实例)拥有独立的成员及状态,互不干涉。虽然JavaScript中没有类这样的机制,但是通过使用闭包,
我们可以模拟出这样的机制。还是以上边的例子来讲:

 

[javascript] view plaincopyprint?
  1. function Person(){    
  2.     var name = "default";       
  3.        
  4.     return {    
  5.        getName : function(){    
  6.            return name;    
  7.        },    
  8.        setName : function(newName){    
  9.            name = newName;    
  10.        }    
  11.     }    
  12. };    
  13.      
  14.      
  15. var john = Person();    
  16. print(john.getName());    
  17. john.setName("john");    
  18. print(john.getName());    
  19.      
  20. var jack = Person();    
  21. print(jack.getName());    
  22. jack.setName("jack");    
  23. print(jack.getName());    
  24.    
  25. 运行结果如下:  
  26.    
  27. default  
  28. john  
  29. default  
  30. jack  

 

由此代码可知,john和jack都可以称为是Person这个类的实例,因为这两个实例对name这个成员的访问是独立的,互不影响的。

分享到:
评论

相关推荐

    waker-fn:将闭包转换为唤醒器

    将闭包转换为唤醒器。 只是一个花哨的回调。 该板条箱将常规的瓶盖转换为唤醒器。 例子 use waker_fn :: waker_fn; let waker = waker_fn ( || println! ( "woken" )); waker. wake_by_ref (); // Prints "woken"....

    SuperClosure一个允许闭包序列化的PHP库

    6. **执行闭包**:反序列化后的闭包可以像普通闭包一样调用。 ```php echo $deserializedClosure('World'); // 输出 "Hello, World" ``` 除了基本的序列化和反序列化,SuperClosure还提供了安全性和灵活性。例如...

    计算NFA中ε闭包

    ### 计算NFA中的ε闭包 #### 一、NFA与ε闭包概念介绍 **非确定有限自动机(NFA)**是一种理论计算模型,它扩展了确定有限自动机(DFA)的概念,允许在某些情况下从一个状态出发到达多个状态。在NFA中,存在一种特殊的...

    原子闭包系统, 原子闭包算子和原子全蕴含系统

    原子闭包系统、原子闭包算子以及原子全蕴含系统是数理逻辑、抽象代数以及数学基础理论中的概念。在本篇文章中,作者杨海建、李庆国和何霞辉对这些概念进行了深入探讨,同时也研究了它们之间的相互关系,并且提出了...

    对于三元闭包的验证.zip

    在IT领域,三元闭包是一个重要的概念,特别是在社交网络分析和图论中。这个理论主要探讨了在社交网络中的关系连接模式,特别是在理解和描述个体之间的互动和连通性时起到关键作用。在这个场景中,"对于三元闭包的...

    Swift 中的闭包和 Objective-C 中的Block

    Swift中的闭包和Objective-C中的Block是两种编程语言中实现匿名函数的关键特性,它们允许我们定义可以在不同上下文中使用的代码块。尽管这两种语言都属于Apple的生态系统,但它们在闭包和Block的概念上有细微差别。 ...

    python高阶闭包练习题

    在Python的世界里,"高阶闭包"是一个高级概念,对于理解函数的内部工作原理和实现更复杂的编程逻辑至关重要。本练习题旨在帮助你深入理解和掌握Python中的高阶闭包。 首先,让我们澄清一下什么是闭包。闭包是Python...

    closure闭包

    在编程语言理论中,"closure"一词通常指的是“闭包”,它是一个非常重要的概念,尤其是在函数式编程和动态类型语言中。闭包是函数和与其相关的引用环境(即变量的值)的组合,这个组合使得函数能够记住它被定义时的...

    王垠导师R. Kent Dybvig的编译器课程(P423)作业文档

    王垠导师R. Kent Dybvig的编译器课程作业文档。跟其他编译原理的课程不同,这门课程是从汇编生成开始,自底向上小步迭代地...第12课的内容是闭包转换,这个网上有很多相关的资料,而且难度也不算太大,自己脑补即可。

    Xcode 插件:用来简化代码格式.zip

    "Xcode 插件:用来简化代码格式.zip"就是这样一个工具,它的主要目标是帮助开发者更方便地处理代码格式,尤其是清理和优化Swift语言中的闭包语法。 闭包是Swift中一个强大的特性,允许我们定义可传递的匿名函数。...

    传递闭包实现

    根据给定文件的信息,我们可以深入探讨“传递闭包”的概念及其在计算机科学中的实现方法。 ### 传递闭包的概念 传递闭包(Transitive Closure)是集合论中的一个概念,指的是在集合\(X\)上的一类特殊的二元关系。...

    数据科学三元闭包验证

    数据科学三元闭包验证是数据挖掘和网络分析中的一个重要概念,主要研究的是在社会网络或图论中,三个人之间的关系强度如何影响彼此之间的连接。三元闭包是指如果个体A与B有联系,B与C有联系,通常情况下,A与C之间也...

    求属性集的属性闭包

    ### 求属性集的属性闭包 在数据库理论中,**属性闭包**是一个重要的概念,尤其是在规范化处理和查询优化方面。它指的是通过一系列函数依赖(Function Dependency, FD),从一个属性集出发所能推导出的所有属性集合...

    Compiling with Continuations

    特别地,它重点讨论了如何将源代码转换为CPS形式,并对编译器内部数据类型、作用域规则、闭包转换和寄存器溢出等问题进行深入讨论。 4. CPS的数据结构和语义:书中详细分析了CPS的数据类型、函数逃逸、作用域规则、...

    数据库属性闭包与应用

    数据库属性闭包与应用 在关系数据库理论中,属性闭包是一个重要的概念,它对数据库逻辑结构设计产生着重要影响。在本文中,我们将结合教学过程中的体会,谈谈属性闭包在关系数据理论中的应用。 首先,让我们来定义...

    闭包和候选码求解.ppt

    闭包和候选码求解 在关系数据库中,闭包和候选码是两个重要的概念。闭包是指在函数依赖关系中,一个属性集合的所有可能的函数依赖关系,而候选码是指一个关系模式中,能够唯一确定其他所有属性的属性集合。本文将...

    用C++程序求出等价闭包

    ### 使用C++求解等价闭包的知识点 在离散数学中,关系的等价闭包是一个重要的概念。本文将详细介绍如何通过C++编程语言实现等价闭包的计算,并对给定代码进行深入分析。 #### 等价闭包的概念 在离散数学中,如果一...

    自动机练习题+答案合集(10份)

    同样,NFA也可以通过ε-闭包转换为DFA。 四、自动机的性质 1. 同步性:DFA的每个状态都是唯一的,而NFA可能存在不确定性。 2. 接受性:自动机中的某个状态可以被标记为接受状态,当输入串结束后落在这个状态,我们...

    跨越边界:闭包

    闭包是一种强大的编程概念,它允许函数访问和操作其外部作用域中的变量,即使在函数执行完毕后仍然能够保持对这些变量的访问。这个特性使得闭包成为函数式编程和面向对象编程中的重要工具,尤其是在诸如Lisp、...

    Groovy Refcards

    闭包是Groovy中最突出的特性之一,它是一个可存储在变量中的代码块,可以访问外部作用域中的变量。闭包提供了强大的功能,如延迟执行、数据绑定等,是实现函数式编程风格的关键。 #### 四、元编程(Metaprogramming...

Global site tag (gtag.js) - Google Analytics