理解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 相关文章推荐
ajax无刷新动态调用股票信息(改良版)
Nov 01 Javascript
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
May 24 Javascript
js触发asp.net的Button的Onclick事件应用
Feb 02 Javascript
一个奇葩的最短的 IE 版本判断JS脚本
May 28 Javascript
JavaScript实现复制或剪切内容到剪贴板功能的方法
May 23 Javascript
使用bat打开多个cmd窗口执行gulp、node
Feb 17 Javascript
浅谈regExp的test方法取得的值变化的原因及处理方法
Mar 01 Javascript
JS实现直接运行html代码的方法
Mar 13 Javascript
基于vue2的table分页组件实现方法
Mar 20 Javascript
Node.js dgram模块实现UDP通信示例代码
Sep 26 Javascript
JS实现进度条动态加载特效
Mar 25 Javascript
html+vue.js 实现漂亮分页功能可兼容IE
Nov 07 Javascript
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中的float类型使用说明
2010/07/27 PHP
PHP变量的定义、可变变量、变量引用、销毁方法
2013/12/20 PHP
可以文本显示的公告栏的js代码
2007/03/11 Javascript
使用jquery实现select添加实现后台权限添加的效果
2011/05/28 Javascript
js从10种颜色中随机取色实现每次取出不同的颜色
2013/10/23 Javascript
js对列表中第一个值处理与jsp页面对列表中第一个值处理的区别详解
2013/11/05 Javascript
Javascript 完美运动框架(逐行分析代码,让你轻松了运动的原理)
2015/01/23 Javascript
基于Node.js的JavaScript项目构建工具gulp的使用教程
2016/05/20 Javascript
js中利用cookie实现记住密码功能
2020/08/20 Javascript
快速入门Vue
2016/12/19 Javascript
JavaScript实现一个简易的计算器实例代码
2018/05/10 Javascript
koa socket即时通讯的示例代码
2018/09/07 Javascript
JavaScript提升机制Hoisting详解
2019/10/23 Javascript
[13:16]INFAMOUS vs VGJ T BO3
2018/06/07 DOTA
python pyheatmap包绘制热力图
2018/11/09 Python
深入浅析python 协程与go协程的区别
2019/05/09 Python
python如何将多个PDF进行合并
2019/08/13 Python
Transpose 数组行列转置的限制方式
2020/02/11 Python
Python3 selenium 实现QQ群接龙自动化功能
2020/04/17 Python
python3通过udp实现组播数据的发送和接收操作
2020/05/05 Python
详解python如何引用包package
2020/06/07 Python
Python如何进行时间处理
2020/08/06 Python
python实现双人五子棋(终端版)
2020/12/30 Python
使用CSS3实现字体颜色渐变的实现
2020/08/10 HTML / CSS
HTML5视频支持检测(检查浏览器是否支持视频播放)
2013/06/08 HTML / CSS
canvas实现漂亮的下雨效果的示例
2018/04/18 HTML / CSS
法国在线宠物店:zooplus.fr
2018/02/23 全球购物
介绍一下javax.servlet.Servlet接口及其主要方法
2015/11/30 面试题
先进工作者获奖感言
2014/02/08 职场文书
525心理活动总结
2014/07/04 职场文书
我的中国梦演讲稿600字
2014/08/19 职场文书
小学教育见习报告
2014/10/31 职场文书
2015年团支书工作总结
2015/04/03 职场文书
公司劳动纪律管理制度
2015/08/04 职场文书
小学教师教学反思
2016/02/24 职场文书
python实战之一步一步教你绘制小猪佩奇
2021/04/22 Python