`
北极的。鱼
  • 浏览: 158989 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

closure(闭包)

阅读更多

对比代码:

 

【代码1】:

function each(){
    var i = 0, inner ,a=[];
    for(;i<10;i++){
        a.push(function(){
            console.log(i);
        })
    }
    return a;
}

var a = each();
for(var i = 0; i < a.length; i++){
    a[i]();
}

 

【代码2】:

function each(){  
    var i = 0, inner ,a=[];  
    for(;i<10;i++){  
        a.push(function(i){  
            console.log(i);
        })  
    }  
    return a;  
}  
      
var a = each();  
for(var i = 0; i < a.length; i++){
    a[i](i);
}

 

【代码3】:

function each(){
    var i = 0, inner ,a=[];
    for(;i<10;i++){
        cache(i);
    }
    function cache(i){
        a.push(function(){
            console.log(i);
        })
    }
    return a;
}

var a = each();
for(var i = 0; i < a.length; i++){
    a[i]();
}

 

【代码4】:

function each(){
    var i = 0, inner ,a=[];
    for(;i<10;i++){
        cache(i);
    }
    function cache(b){//这段代码和上一段代码比较目的在于,cache函数的参数被内部函数引用,无关参数名
        a.push(function(){
            console.log(b);
        })
    }
    return a;
}

var a = each();
for(var i = 0; i < a.length; i++){
    a[i]();
}

 

【代码6】:

function each(){
    var i = 0, inner ,a=[];
    for(;i<10;i++){
        cache(i);
    }
    function cache(){
        a.push(function(){
            console.log(i);
        })
    }
    return a;
}

var a = each();
for(var i = 0; i < a.length; i++){
    a[i]();
}

 

【代码7】:

var body = document.body;   
var items = ["click","mousemove"];   
for(var i = 0;i<items.length;i++){   
    (function(){ //自运行函数开辟了一个新的域,和外层的for明显不在一个域中
        var item = items[i];//但是这里每次都保存了外层的for的临时变量。
        body["on"+item] = function(){   
            console.log(item);
        }   
    })()   
}  

 

 

【代码8】:

var body = document.body;   
var items = ["click","mousemove"];   
(function(){  
    for(var i = 0;i<items.length;i++){   
        var item = items[i];   
        body["on"+item] = function(){//函数开辟了一个新的域,和外层的for明显不在一个域中,顾item引用了外层的最终值
            console.log(item);
        }   
    }
})()   

 

【代码9】:

function User(pr){
    for(var i in pr){
        (function(which){
            var p =i;//因为这里定义的自运行函数和外部的for语句已经不在同一个域中了,如果不保存临时的变量,那么将得到最终值
            which["get"+p] = function(){
                return pr[p];
            };
            which["set"+p] = function(val){
                pr[p] = val;
            }
        })(this)
    }
}
var u = new User({name:"louis",age:25})
alert(u.getname())
alert(u.getage())

 

【代码10】:

function User(pr){
    for(var i in pr){
        (function(which){
            //var p =i;//每次for循环都会临时保存变量的值(i),但是如果这个临时保存的值这里没有被记录下来,那么内层定义的函数依旧是去找引用的变量所在的定义层(这里是自运行函数的外层函数)的最终值。所以这里i就是去找pr对象中的最后一个属性。
//这里在引用下JQuery之父的解释:闭包允许你引用父函数中的变量,但是提供的值并非该变量创建时的值,而是父函数范围内的最终值。
//所以说,判断某个函数引用的值到底是什么?需要1.判断该函数是不是定义在另一个函数体中?2.引用的值是不是外层函数定义的?
            which["get"+i] = function(){
                return pr[i];
            };
            which["set"+i] = function(val){
                pr[i] = val;
            }
        })(this)
    }
}
var u = new User({name:"louis",age:25})
alert(u.getname())
alert(u.getage())

 

【Tips】:

函数的闭包,一定要定义在某个函数内部,才能获得这个函数的变量的最终值! 

 

 

【总结】:

个人理解,闭包其实就是连接函数内部世界与外部世界的一个桥梁。作为闭包,首先,闭包所在父函数的内部的私有成员,肯定是不能直接被外部访问的。外部要访问闭包所在的父函数内部的成员,就需要提供一个接口,闭包就担任这个任务!所以可以理解其为一个桥梁,一端是函数内部的封闭世界,另一段是外部的操作。大家也可以理解闭包所在的父函数就像是一个黑匣子,闭包就是提供对外的一个接口了。

 

 

 

0
0
分享到:
评论
5 楼 北极的。鱼 2014-07-22  
最后归纳总结一下:

闭包就是一个函数定义在另一个函数的定义中(也就是嵌套定义函数)。

当内部函数引用外部函数定义的变量时,会得到这个变量的最终值,不管外部函数是不是一个自运行函数形成的一个域。
但是对于一个自运行函数形成的域,确实有一点特殊,在于这个域可以用一个变量记录外部每次循环产生的临时变量值,这样内部的函数就能通过这个自运行函数中的临时变量来得到不同的值,或者还有一个方案就是把外层循环的变量当作参数传递给自运行函数。但是如果采用这两种方案的话,终究还是得到外部变量的最终值。(具体看4楼的例子,第二个方案看如下:)

var body = document.body;    
for(var i = 0;i<3;i++){   
    (function(i){//这里是把每次的临时变量i都传递给自运行函数,也能获得不同的值  
        body.addEventListener("click",function(){console.log(i) },true)  
    })(i)   
} 
4 楼 北极的。鱼 2014-07-21  
再给2个对比函数。
【代码1:】
var body = document.body;    
for(var i = 0;i<3;i++){   
    (function(){//每次for循环,自运行函数都将运行一次,产生一个新的域   
        //var item = i;//这里,如果不保存每次的临时变量,还是得到的最终值
        body.addEventListener("mousemove",function(){console.log(i) },true)  
    })()   
} 

输出为3,3,3……(为什么会是3?因为当i循环到3的时候,退出循环了,但是这却是i的最终值)

【代码2:】
var body = document.body;    
for(var i = 0;i<3;i++){   
    (function(){   
        var item = i;   
        body.addEventListener("mousemove",function(){console.log(item) },true)  
    })()   
} 

输出为0,1,2……
3 楼 北极的。鱼 2014-07-20  
另一个解释:
在函数声明处向外部看到的声明的所有的变量,在函数内部都能访问到他们的最终值。
2 楼 北极的。鱼 2011-08-14  
函数声明处向函数外看到的声明的所有变量,在函数内部都能访问到他们的最终值

当闭包函数内引用能见到的某个变量时,如果这个变量不是在闭包的直接宿主函数体内的话,那么闭包会向再外一层宿主函数索要引用的这个变量的最终值。以此类推,直到最外层。

for语句有临时保存变量的作用,但是一定要看清for语句和闭包函数的层次关系。
如果同时存在于宿主函数内部,那么将得到for循环后,变量的最终值。
如果宿主函数存在于for循环的内部,那么闭包中引用的变量将是每次for循环得到的临时值。
1 楼 Coder211 2011-04-16  
呵呵,很抽象!!

相关推荐

    closure闭包

    在描述中提到的"求文法的closure闭包"实际上可能是指在编译器设计和解析理论中的另一个概念,与编程语言中的闭包不同。这里所说的"closure"可能是关于正规文法的扩展,即E-closure。在正规文法中,E-closure是对一个...

    Swift语言利用Closure闭包实现反向传值Demo

    在本Demo“Swift语言利用Closure闭包实现反向传值Demo”中,我们将深入探讨如何利用闭包在两个视图控制器之间实现数据的反向传递。 首先,理解闭包的基本概念。闭包本质上是一个函数,它可以访问并修改其外部作用域...

    Swift语言采用Closure闭包实现反向传值Demo

    在这个"Swift语言采用Closure闭包实现反向传值Demo"中,我们将深入探讨如何使用闭包在两个视图控制器之间进行反向数据传递,以及它与Blocks的异同。 首先,让我们了解什么是闭包。闭包是能够捕获和存储其所在上下文...

    Swift语言采用Closure闭包进行传值Demo

    在Swift中,Closure(闭包)是一种强大的功能,可以捕获和存储其所在上下文中的引用。本Demo通过闭包展示了在两个视图控制器之间如何实现反向传值,这与Objective-C(OC)中的Blocks概念有相似之处,但也有其独特之...

    Closure闭包函数示例

    补充说明:闭包可以使用USE关键连接外部变量。 总结:PHP闭包的特性其实用CLASS就可以实现类似甚至强大得多的功能,更不能和js的闭包相提并论了吧,只能期待PHP以后对闭包支持的改进。不过匿名函数还是挺有用的,...

    closure闭包1

    - 在Groovy中,闭包是 `groovy.lang.Closure` 类的实例,这意味着你可以将闭包赋值给变量,作为参数传递,或者作为其他对象的字段。例如: ```groovy def myClosure = { println 'Hello, World!' } ``` 3. **...

    Python closure闭包解释及其注意点详解

    在Python编程语言中,闭包(closure)是一种常见的概念,它涉及到函数和作用域,经常会在代码中扮演重要角色。理解闭包及其相关注意事项,对于编写高效、正确的Python代码来说至关重要。本文档详细解释了闭包的概念...

    Python闭包实例closure.py

    Python闭包实例closure.py 简单示例闭包的使用 简单示例闭包的使用

    前端大厂最新面试题-closure.docx

    闭包(Closure)是 JavaScript 中的一种机制,它允许函数访问其外层函数的变量。闭包的主要特点是可以在一个内层函数中访问到其外层函数的作用域。 一、闭包的定义 闭包是指一个函数和对其周围状态(lexical ...

    LR 分析方法程序设计原理与实现技术

    ##### 3.1 CLOSURE闭包的求取 闭包(CLOSURE)是指在一个项目集中添加所有可能产生的新项目的过程,直到没有新的项目可以添加为止。具体步骤如下: 1. 对于给定的项目集I中的每一个产生式A → α·Xβ (其中X是非终结...

    计算NFA中ε闭包

    3. **ε闭包计算**:`E_closure`函数采用递归方式实现,对于每个状态,它会输出该状态的所有ε闭包状态,并递归地计算这些状态的ε闭包。 4. **主函数**:`main()`函数中调用了`input()`函数读取NFA描述信息,并...

    JavaScript知识点总结(十六)之Javascript闭包(Closure)代码详解

    闭包(Closure)是一个可以包含自由变量的代码块,这个自由变量并不是在这个代码块或任何全局上下文中定义的,而是在定义代码块的环境中定义。简单来说,闭包就是在一个函数内部定义另一个函数,内层函数可以引用...

    闭包权威指南] Closure:The Definitive Guide Michael Bolin

    《闭包:权威指南》(Closure: The Definitive Guide)由Michael Bolin撰写,于2010年由O'Reilly Media出版。本书是关于JavaScript闭包的深度解析与应用实践的权威之作,深入探讨了闭包在JavaScript中的各种应用场景...

    php5.4中文手册

    4. ** Closure 闭包**:PHP5.4支持匿名函数,也称为闭包。它们可以作为值传递,可以保存到变量中,也可以作为参数传递给其他函数,或者作为其他函数的返回值。 5. **内置Web服务器**:PHP5.4引入了一个简单的内置...

    Lua学习笔记之函数、变长参数、closure(闭包)、select等

    本文将介绍Lua中函数的基础用法、变长参数、closure(闭包)、以及select函数的使用,并结合代码实例进行详细说明。 首先,Lua函数支持多返回值。例如,在使用`string.find`函数查找子串时,该函数会返回两个值,...

    JavaScript闭包(closure).pdf

    JavaScript中的闭包是一种高级特性,它是函数和其周围状态(词法作用域)的组合,即使函数在其定义的作用域之外被调用,它仍然能访问到这些状态。这个概念是JavaScript编程中的核心部分,尤其在处理异步操作、模块化...

    Javascript 闭包完整解释

    当`outerFunction(10)`被调用时,它返回了一个闭包`closure`,即使`outerFunction`已经执行完毕,`closure`仍然可以访问到`x`的值。 #### 六、闭包的注意事项 尽管闭包非常强大,但在使用时也需要注意以下几点: ...

    python中闭包Closure函数作为返回值的方法示例

    首先看看闭包的概念:闭包(Closure)是词法闭包(Lexical Closure)的简称,是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,闭包是由函数和与其...

    理解javascript函数式编程中的闭包(closure)_.docx

    本篇文章主要探讨JavaScript函数式编程中的一个重要概念——闭包(closure)。闭包是一种特殊的函数,它能记住其定义时的作用域,即使在函数执行完毕后,仍然可以访问到该作用域内的变量。在JavaScript中,每个函数...

Global site tag (gtag.js) - Google Analytics