理解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 相关文章推荐
两个SUBMIT按钮,如何区分处理
Aug 22 Javascript
javascript函数声明和函数表达式区别分析
Dec 02 Javascript
jquery计算鼠标和指定元素之间距离的方法
Jun 26 Javascript
深入浅析同源策略和跨域访问
Nov 26 Javascript
js实现的彩色方块飞舞奇幻效果
Jan 27 Javascript
babel之配置文件.babelrc入门详解
Feb 22 Javascript
浅谈vue 单文件探索
Sep 05 Javascript
解决vue v-for 遍历循环时key值报错的问题
Sep 06 Javascript
在vue-cli的组件模板里使用font-awesome的两种方法
Sep 28 Javascript
js核心基础之闭包的应用实例分析
May 11 Javascript
Node4-5静态资源服务器实战以及优化压缩文件实例内容
Aug 29 Javascript
vue完美实现el-table列宽自适应
May 08 Vue.js
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性能的原理介绍
2012/09/05 PHP
解析php中两种缩放图片的函数,为图片添加水印
2013/06/14 PHP
php foreach正序倒序输出示例代码
2014/07/01 PHP
php通过获取头信息判断图片类型的方法
2015/06/26 PHP
php 读取文件夹下所有图片、文件的实例
2018/10/17 PHP
Centos7.7 64位利用本地完整安装包安装lnmp/lamp套件教程
2021/03/09 Servers
jquery 事件对象属性小结
2010/04/27 Javascript
基于Jquery插件开发之图片放大镜效果(仿淘宝)
2011/11/19 Javascript
jQuery简单实现验证邮箱格式
2015/07/15 Javascript
jquery合并表格中相同文本的相邻单元格
2015/07/17 Javascript
AngularJS入门教程之更多模板详解
2016/08/19 Javascript
AngularJS压缩JS技巧分析
2016/11/08 Javascript
easyui combobox开启搜索自动完成功能的实例代码
2016/11/08 Javascript
JS创建Tag标签的方法详解
2017/06/09 Javascript
微信小程序实现YDUI的ScrollNav组件
2018/02/02 Javascript
js捆绑TypeScript声明文件的方法教程
2018/04/13 Javascript
nuxt引入组件和公共样式的操作
2020/11/05 Javascript
Linux下使用python自动修改本机网关代码分享
2015/05/21 Python
Python编程中time模块的一些关键用法解析
2016/01/19 Python
基于Python的关键字监控及告警
2017/07/06 Python
python3判断url链接是否为404的方法
2018/08/10 Python
Laravel+Dingo/Api 自定义响应的实现
2019/02/17 Python
pycharm导入源码的具体步骤
2020/08/04 Python
彻底弄明白CSS3的Media Queries(跨平台设计)
2010/07/27 HTML / CSS
NARS化妆品官方商店:美国彩妆品牌
2017/08/26 全球购物
final, finally, finalize的区别
2012/03/01 面试题
美术国培研修感言
2014/02/12 职场文书
学雷锋月活动总结
2014/04/25 职场文书
环保倡议书300字
2014/05/15 职场文书
广播节目策划方案
2014/05/23 职场文书
领导班子四风表现材料
2014/08/23 职场文书
《爱的教育》读书心得
2014/11/08 职场文书
慰问信模板
2015/02/14 职场文书
写给导师的自荐信
2015/03/06 职场文书
小学运动会入场词
2015/07/18 职场文书
重温经典:乔布斯在斯坦福大学的毕业演讲(双语)
2019/08/26 职场文书