关闭

javascript闭包的应用

标签: javascript闭包
1565人阅读 评论(0) 收藏 举报
分类:

我印象中,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/ 上运行一下这些代码,加以印证、对照。

    0
    0
    查看评论

    JavaScript 的闭包用于什么场景

    本文翻译自 MDN ( Mozilla Developer Network ): 原文地址:MDN 译文地址:shixinzhang 的博客 词法作用域考虑如下代码:function init() { var name = 'Mozilla'; // name 是 init 函数...
    • u011240877
    • u011240877
    • 2017-04-17 01:16
    • 2944

    浅析JavaScript闭包

    闭包和原型是javascript语言的两大特点,上篇博文浅析JavaScript原型 中已经总结了原型 ,今天就总结一下闭包的相关知识。 前言 在开始闭包之前,需要先介绍一下匿名函数和JavaScript垃圾回收机制这两个概念。 匿名函数 匿名函数,很容易理解,就是没有名字...
    • u010773667
    • u010773667
    • 2015-02-15 12:17
    • 1124

    JavaScript闭包的原理与缺陷

    闭包的原理闭包是指有权访问另一个函数作用域中的变量的函数。根据下面的代码示例来理解什么是闭包,在add函数内部的匿名函数中,访问到外部函数的变量outerArg,在执行add(10)之后外部函数返回了,并且将内部的匿名函数赋值给了变量addTen,此时通过addTen调用函数,依然可以访问到oute...
    • hongchh
    • hongchh
    • 2016-08-16 16:37
    • 1423

    JavaScript 的闭包原理与详解

    JavaScript 的闭包原理与详解。JavaScript的闭包是一个特色,但也是很多新手难以理解的地方,阅读过不少大作,对闭包讲解不一,个人以为,在《JavaScript高级程序设计》一书中,解释的最为详尽,结合此书,表述一下我对JavaScript闭包的理解,希望能对新手有些帮助。闭包的例子v...
    • qq_29594393
    • qq_29594393
    • 2016-10-26 18:24
    • 1181

    记python中的闭包应用

    今天我们来看一下函数的闭包(closure)。python中学到高级语法,闭包是逃不开的话题,无论是高阶函数还是装饰器等,不理解闭包会寸步难行。     来看代码 def count(): fs = [] for i in range(1, 4): ...
    • Rubik_Wong
    • Rubik_Wong
    • 2016-12-15 21:29
    • 373

    闭包的常见应用

    事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。 1、匿名自执行函数 我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处, 比如:别的函数可能误用这...
    • qq_34986769
    • qq_34986769
    • 2016-08-10 14:26
    • 808

    闭包的实际应用(更新中。。。)

    1、匿名自执行函数  我们知道所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去,这样的临时变量加入全局对象有很多坏处, 比如:别的函数可能误用这些变量;造成全局对象过于庞大,影响访问速度(因为变量的取值是需要从原型链上遍历的)。 除了每次使用变量都是用var关键字外,我们在...
    • ForMyQianDuan
    • ForMyQianDuan
    • 2016-07-13 19:45
    • 1387

    javascript递归与闭包

    转自Javascript高级程序设计(第三版): 定义函数的方法有两种: 一种是函数声明,另一种是函数表达式。 关于函数声明,最重要的特征就是:函数声明提升(function declaration hoisting),也就是在执行代码之前会读取函数声明。这就意味着可以把函数声明放在调用它的语句后面...
    • u013250416
    • u013250416
    • 2015-08-13 10:28
    • 463

    javascript理解之变量作用域与闭包

    何为闭包闭包是指能够访问自由变量的函数 (变量在本地使用,但在闭包中定义)。换句话说,定义在闭包中的函数可以“记忆”它被创建时候的环境。函数作用域与声明提前var scope= "global scope"; function f(){ console.log(scope);...
    • sinat_25127047
    • sinat_25127047
    • 2016-06-12 17:33
    • 1434

    Javascript 中 作用域、闭包与 this 指针

    js 中的作用域,闭包的理解和运用,this 的理解和运用
    • JunBo_Song
    • JunBo_Song
    • 2016-08-20 14:17
    • 4571
      个人资料
      • 访问:2518844次
      • 积分:34029
      • 等级:
      • 排名:第158名
      • 原创:919篇
      • 转载:0篇
      • 译文:0篇
      • 评论:627条
      文章分类
      最新评论