理解Javascript闭包


Posted in Javascript onNovember 01, 2013

闭包是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)。
闭包主要的问题便是它会保存包含它的函数的作用域,因此比一般函数占用更多的内存空间,因此不宜过度使用闭包。

闭包的应用

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

Javascript 相关文章推荐
javascript基础知识大集锦(一) 推荐收藏
Jan 13 Javascript
Node.js:Windows7下搭建的Node.js服务(来玩玩服务器端的javascript吧,这可不是前端js插件)
Jun 27 Javascript
jQuery的12招常用技巧分享
Aug 08 Javascript
JSP跨iframe如何传递参数实现代码
Sep 21 Javascript
js 去掉空格实例 Trim() LTrim() RTrim()
Jan 07 Javascript
javaScript 页面自动加载事件详解
Feb 10 Javascript
jQuery实现3D文字特效的方法
Mar 10 Javascript
javaScript中slice函数用法实例分析
Jun 08 Javascript
javascript实现的登陆遮罩效果汇总
Nov 09 Javascript
JS中使用apply方法通过不同数量的参数调用函数的方法
May 31 Javascript
深入浅析Vue中的Prop
Jun 10 Javascript
jQuery实现轮播图及其原理详解
Apr 12 jQuery
Javascript 命名空间模式
Nov 01 #Javascript
完美解决AJAX跨域问题
Nov 01 #Javascript
javascript中创建对象的几种方法总结
Nov 01 #Javascript
如何学习Javascript入门指导
Nov 01 #Javascript
js动态设置鼠标事件示例代码
Oct 30 #Javascript
获取非最后一列td值并将title设为该值的方法
Oct 30 #Javascript
eclipse如何忽略js文件报错(附图)
Oct 30 #Javascript
You might like
PHP 长文章分页函数 带使用方法,不会分割段落,翻页在底部
2009/10/22 PHP
php 无限级数据JSON格式及JS解析
2010/07/17 PHP
php 批量添加多行文本框textarea一行一个
2014/06/03 PHP
CodeIgniter整合Smarty的方法详解
2017/08/25 PHP
十个优秀的Ajax/Javascript实例网站收集
2010/03/31 Javascript
关于IE浏览器以及Firefox下的javascript冒泡事件的响应层级
2010/10/14 Javascript
JQuery中getJSON的使用方法
2010/12/13 Javascript
js中有关IE版本检测
2012/01/04 Javascript
两个listbox实现选项的添加删除和搜索
2013/03/01 Javascript
css transform 3D幻灯片特效实现步骤解读
2013/03/27 Javascript
javascript获取URL参数与参数值的示例代码
2013/12/20 Javascript
jquery插件推荐 jquery.cookie
2014/11/09 Javascript
javascript 数组操作详解
2015/01/29 Javascript
JavaScript中原型和原型链详解
2015/02/11 Javascript
Javascript removeChild()删除节点及删除子节点的方法
2015/12/27 Javascript
JS弹出层遮罩,隐藏背景页面滚动条细节优化分析
2016/04/29 Javascript
JavaScript中undefined和null的区别
2017/05/03 Javascript
VUE前后端学习tab写法实例
2019/08/06 Javascript
vue中v-model对select的绑定操作
2020/08/31 Javascript
Python 获得13位unix时间戳的方法
2017/10/20 Python
对Python3中的input函数详解
2018/04/22 Python
Python求解任意闭区间的所有素数
2018/06/10 Python
一行代码让 Python 的运行速度提高100倍
2018/10/08 Python
解决pycharm运行出错,代码正确结果不显示的问题
2018/11/30 Python
python3使用GUI统计代码量
2019/09/18 Python
pycharm激活码快速激活及使用步骤
2020/03/12 Python
Django框架安装及项目创建过程解析
2020/09/14 Python
微软开源最强Python自动化神器Playwright(不用写一行代码)
2021/01/05 Python
python用700行代码实现http客户端
2021/01/14 Python
通用C#笔试题附答案
2016/11/26 面试题
人事助理岗位职责
2013/11/18 职场文书
大学系主任推荐信范文
2013/12/24 职场文书
大学生社会实践自我鉴定
2014/03/24 职场文书
廉洁自律演讲稿
2014/05/22 职场文书
教师廉政准则心得体会
2016/01/20 职场文书
《刺客之王:C罗全景传记》:时代从来不会亏待手艺人
2019/11/28 职场文书