理解Javascript闭包

 更新时间:2013年11月01日 11:09:56   作者:  
闭包是ECMAScript一个很重要的特征,但是却很难用合适的定义来描述它。虽然闭包很难清晰地描述,但是,却很容易创建,或者说,不小心创建。然而,闭包的存在其实是有一定的潜在问题的。为了避免“不小心”地创建闭包,以及更好地利用闭包的优点,有必要理解闭包的机制

闭包是ECMAScript一个很重要的特征,但是却很难用合适的定义来描述它。虽然闭包很难清晰地描述,但是,却很容易创建,或者说,不小心创建。然而,闭包的存在其实是有一定的潜在问题的。为了避免“不小心”地创建闭包,以及更好地利用闭包的优点,有必要理解闭包的机制。

闭包的定义
 
关于闭包,有太多的定义,特别是有一些定义非常抽象,象这个:

A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables.

大致是说闭包是一个表达式,拥有一些自由变量及绑定这些变量的执行环境。这种定义太书面化,反而难以理解。

还有另一个定义:
所有函数都是闭包。这个定义给我很大的迷惑,换句话说,由于Javascript没有块级作用域,因此闭包一般指的是函数(想不出除了函数以外还有哪些方式可以构成闭包)。

这里不想太多讨论函数与闭包的关系,下面给出我认为比较容易理解的定义吧。

首先,闭包的存在是基于作用域链。由于作用域链的机制,所有函数(即使全局函数)都能引用上下文执行环境中的变量(即free variables)。

其次,闭包内部必须有free variables。顺便说下两种变量1. Local variables (bound variables) 2. Non-local variables (free variables)

最后,在其上下文环境结束后仍然存在。即内部函数拥有比它的外部函数更长的生命周期。

 
关于闭包定义的解析
 
关于闭包定义的两点,一直在考虑是不是必须同时满足。

首先,如果闭包内部没有free variables,即是说它没有访问外部的变量,那么就失去了闭包的意义。(除非通过其他闭包改变了行为)因此,我认为free variables是必要条件。

其次,如果函数内部存在free variables,但是当其上下文环境销毁后,它也跟着销毁。可以想象内部函数,虽然访问了其外部函数变量,但是当外部函数执行完后也随之回收。这种情况下,闭包的讨论也没有意义。

 
来看两个例子:

复制代码 代码如下:

var objectA = (function() {
        var localA = "localA";

        innerFn();
              // 单纯的内部函数调用
        function innerFn() {
            localA = "innerChange";
        }

        return {
            getLocalA : function() {
                return "empty";
            }
        };
    })();

    objectA.getLocalA();

    objectA.getLocalA = function() {
        return localA;
    };

    //console.log(objectA.getLocalA()); //error: localA is not defined

 
    var objectB = (function() {
        var localB = "localB";

        return {
            getLocalB : function() {
                return "empty";
            },

            updateGetLocalB : function() {
                this.getLocalB = function() {
                    return localB;
                };
            },

            updateLocalB : function() {
                localB = "changeLocalB";
            }
        };
    })();

    console.log(objectB.getLocalB()); // empty
       // 通过其他闭包改变
    objectB.updateGetLocalB();

    console.log(objectB.getLocalB()); // localB

    objectB.updateLocalB();

    console.log(objectB.getLocalB()); // changeLocalB

闭包的优点和缺点

闭包的优点是闭包内部可以访问到定义它们的外部函数的参数和变量(除了this和arguments)。
闭包主要的问题便是它会保存包含它的函数的作用域,因此比一般函数占用更多的内存空间,因此不宜过度使用闭包。

闭包的应用

闭包最基本的应用场景便是通过保护内部变量从而实现私有,比如模块模式。

相关文章

  • json字符串对象转换代码实例

    json字符串对象转换代码实例

    这篇文章主要介绍了json字符串对象转换代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • js 剪切板应用clipboardData详细解析

    js 剪切板应用clipboardData详细解析

    本篇文章主要介绍了js剪切板应用clipboardData。需要的朋友可以过来参考下,希望对大家有所帮助
    2013-12-12
  • JavaScript实现雪花飘落效果

    JavaScript实现雪花飘落效果

    这篇文章主要为大家详细介绍了JavaScript实现雪花飘落效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-12-12
  • 微信小程序开发经验总结(推荐)

    微信小程序开发经验总结(推荐)

    本篇文章主要介绍了微信小程序开发经验总结(推荐),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-01-01
  • 关于layer.js使用心得-向弹出框传值问题

    关于layer.js使用心得-向弹出框传值问题

    这篇文章主要介绍了关于layer.js使用心得-向弹出框传值问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • NodeJS的Promise的用法解析

    NodeJS的Promise的用法解析

    下面小编就为大家带来一篇NodeJS的Promise的用法解析。小编觉得挺不错的,现在分享给大家,也给大家做个参考
    2016-05-05
  • JavaScript Dom实现轮播图原理和实例

    JavaScript Dom实现轮播图原理和实例

    这篇文章主要为大家详细介绍了JavaScript Dom实现轮播图原理和实例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-02-02
  • js html实现计算器功能

    js html实现计算器功能

    这篇文章主要为大家详细介绍了js html实现计算器功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-11-11
  • Chart.js与ECharts.js图表使用过程组件对比

    Chart.js与ECharts.js图表使用过程组件对比

    chartjs只能基于canvas,虽然只有英文文档,但定制化程度更高,社区成熟,功能就更加稳定,ECharts.js可以基于svg或者canvas去渲染,有融合主流前端框架的社区库,另外ECharts.js还支持3d效果的图表,相当炫酷,国内开发者大多数使用这个,有中文文档
    2023-10-10
  • js匿名函数的调用示例(形式多种多样)

    js匿名函数的调用示例(形式多种多样)

    匿名函数就是没有实际名字的函数,javaScript的匿名函数形式多样,下面就一一为大家罗列出来
    2014-08-08

最新评论