我印象中,javascript的闭包属于进阶的范畴,无非是用来在面试中装装逼而已。你看我身边的一个小伙子,有一天我装逼地问他什么是javascript的闭包,他居然连听都没听说过。但他做起前端的东西来很快,就像我见过的其他小伙子一样。

这说明,知不知道闭包,似乎无关重要。

但是,这几天写了一些前端代码,觉得还是应该要了解这个东西。

所谓的闭包,按我的理解,就是一个javascript函数(父函数)里面有子函数,然后外界可以通过这个子函数来访问到父函数里面的变量。闭包的作用在于保护这些父函数里的变量,使得这些变量在父函数运行期结束后,继续存活,免遭javascript垃圾回收机制所回收。

怎么理解呢?举例说明。

比如说,我们在页面上输出一堆列表项,每个列表项都有一个onclick事件:

<ul>
<li id="li1" onclick="hi(1)">我是1</li>
<li id="li2" onclick="hi(2)">我是2</li>
...
</ul>

我们会发现,列表项存在着许多重复代码,造成页面代码很多。如果我们不预先给每个

  • 设置事件,而是在页面加载完毕以后,再给它们绑定onclick事件,这样页面就简洁许多,减少带宽的消耗。
  • 那么,如何绑定事件呢?假如我们这样写:

    function hi(number){
    alert("我是 " + number + " !");
    }
    $(function(){
    for(var i = 1;i <= 100; i++){
    $("#li" + i).bind("click",function(){
    hi(i);
    });
    }
    });

    那么最终,点击每个列表项,都会显示 “我是 100 !”。原因是循环结束后,i是100。

    如果换成这样子:

    function hi(number){
    return function(){//子函数,闭包机制将传入的number存储起来
    alert("我是 " + number + " !");
    };
    }
    $(function(){
    for(var i = 1;i <= 100; i++){
    $("#li" + i).bind("click",hi(i));
    }
    });

    那么就可以得到我们想要的结果。原因是,函数hi(number)中,建立了闭包,在事件绑定的时候,将传过来的i储存起来了。

    要理解上述语句,有必要对事件绑定这里做一些说明:

    $("#li" + i).bind("click",函数定义);

    意思是,绑定给元素事件的,是函数定义,而不是一个函数运行语句!一定要清楚这一点。比如说,function hi(numbert){…}是函数定义,hi(i)就是一个函数运行语句。

    我们对代码稍加修改,对比来看一下:

    function hi(number){//函数体内是普通的执行语句
    alert("我是急性子 " + number + " !");
    }
    function hi_bb(number){//函数体内返回一个子函数实例
    return function(){//子函数,闭包
    alert("我是 " + number + " !");
    };
    }
    $(function(){
    for(var i = 1;i < 3; i++){
    //此时hi执行,一次性弹出信息,绑定失败
    $("#li" + i).bind("click",hi(i));
    //此时hi_bb执行,返回了一个函数定义,绑定成功
    $("#li" + i).bind("click",hi_bb(i));
    }
    });

    在事件绑定的时候,函数hi、hi_bb都执行了。hi里面是普通的执行语句,呼啦啦的一下执行完毕,列表项未能绑定事件;而hi_bb执行后,返回的是函数定义,因此列表项事件绑定成功。

    让我们再回顾一下闭包的作用:保护父函数里的变量,使得这些变量在父函数运行期结束后,继续存活,免遭javascript垃圾回收机制所回收。 本文例子中,事件绑定之时,hi_bb执行,i作为参数传入。本来循环语句、页面onload函数结束,i就应该不存在了。但因为hi_bb里有闭包,每一个i的值都保存了下来,在以后的点击事件中,发挥出应有的作用。

    这些话好像有些勉强和装逼,我也是在体会中。如果是面向对象语言,这很好理解,对象构造自同一个类,而对象里的属性、变量的值却是不同的。把参数通过构造函数、成员方法,或者属性设置传给对象的属性或成员变量以后,对象就会将它们保存下来。javascript不是面向对象,没有类,只有函数。也许闭包就是它的一种面向对象的模拟。我是这么理解的。

    我以前也总结过闭包,现在又写了一篇,感觉又加深了一点理解:

    http://blog.csdn.net/leftfist/article/details/41868659

    可以在网站 http://jsfiddle.net/ 上运行一下这些代码,加以印证、对照。

    版权声明:本文为博主原屙文章,喜欢你就担走。

    javascript闭包的应用的更多相关文章

    1. 《Web 前端面试指南》1、JavaScript 闭包深入浅出

      闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

    2. JavaScript 闭包深入浅出

      闭包是什么? 闭包是内部函数可以访问外部函数的变量.它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量. 内部函数不仅可以访问外 ...

    3. JavaScript闭包(Closure)

      JavaScript闭包(Closure) 本文收集了多本书里对JavaScript闭包(Closure)的解释,或许会对理解闭包有一定帮助. <你不知道的JavsScript> Java ...

    4. Javascript闭包和C#匿名函数对比分析

      C#中引入匿名函数,多少都是受到Javascript的闭包语法和面向函数编程语言的影响.人们发现,在表达式中直接编写函数代码是一种普遍存在的需求,这种语法将比那种必须在某个特定地方定义函数的方式灵活和 ...

    5. javascript闭包理解

      //闭包理解一 function superFun(){ var _super_a='a'; function subfuc(){ console.log(_super_a); } return su ...

    6. Javascript闭包深入解析及实现方法

      1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点:1. 作为一个函数变量的一个引用,当函数返回时 ...

    7. javascript闭包和作用域链

      最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...

    8. JavaScript闭包深入解析

      for (var i=1; i<=5; i++) { setTimeout( function timer() { console.log( i ); }, i*1000 ); } --上面这段 ...

    9. JavaScript 闭包系列二(匿名函数及函数的闭包)

      一. 匿名函数 1. 函数的定义,可分为三种 1) 函数声明方式 function double(x) {     return 2*x; } 2)Function构造函数,把参数列表和函数体都作为字 ...

    10. JavaScript闭包模型

        JavaScript闭包模型 -----  [原创翻译]2016-09-01  09:32:22 < 一>  闭包并不神秘 本文利用JavaScript代码来阐述闭包,目的是为了使普通 ...

    随机推荐

    1. 剑指Offer(书):机器人的运动范围

      题目:地上有一个m行和n列的方格.一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子. 例如,当k为18时,机器人能够进 ...

    2. POJ 2349 Arctic Network(贪心 最小生成树)

      题意: 给定n个点, 要求修p-1条路使其连通, 但是现在有s个卫星, 每两个卫星可以免费构成连通(意思是不需要修路了), 问修的路最长距离是多少. 分析: s个卫星可以代替s-1条路, 所以只要求最 ...

    3. 算法导论 第六章 2 优先队列(python)

      优先队列:     物理结构: 顺序表(典型的是数组){python用到list}     逻辑结构:似完全二叉树 使用的特点是:动态的排序..排序的元素会增加,减少#和快速排序对比 快速一次排完 增 ...

    4. Spring使用JdbcTemplate实现对数据库操作

      https://www.cnblogs.com/tuhooo/p/6491913.html https://blog.csdn.net/maodoubi/article/details/4826723 ...

    5. TOJ 2944 Mussy Paper

      2944.   Mussy Paper Time Limit: 2.0 Seconds   Memory Limit: 65536K    Special JudgeTotal Runs: 381  ...

    6. xtu summer individual 4 C - Dancing Lessons

      Dancing Lessons Time Limit: 5000ms Memory Limit: 262144KB This problem will be judged on CodeForces. ...

    7. NOIP2009T3最优贸易(Dfs + spfa)

      洛谷传送门 看到这个题,原本想先从后往前dfs,求出能到终点的点,再在这些点里从前往后spfa,用一条边上的两个城市的商品价格的差来作边权,实施过后,发现图中既有负边权,又有回路,以及各种奇奇怪怪的东 ...

    8. iOS时钟,秒针扫秒样式

      昨天做一个时钟小demo,发现了一些问题. 描述能力有限,我封装好了一个时钟框架,朋友们可以参考      https://github.com/qianlishun/ClockView 点击这里可以 ...

    9. BZOJ1742: [Usaco2005 nov]Grazing on the Run 边跑边吃草

      数轴上n<=1000个点,从p出发以任意顺序走到所有的点,求到达每个点的时间之和的最小值. 好题!看起来水水的实际易错! 显然的结论是经过一个区间点之后肯定落在左端点或右端点上,谁没事最后还往中 ...

    10. 解决ssh无操作自动断开[转载,已经验证]

      用SSH远程,如果几分钟没有任何操作,连接就会断开,必须重新登陆才行,非常麻烦,一般修改2个地方3项即可解决问题: 1.终端键入:echo $TMOUT       如果显示空白,表示没有设置,等于使 ...