JavaScript闭包(Closure)

本文收集了多本书里对JavaScript闭包(Closure)的解释,或许会对理解闭包有一定帮助。

《你不知道的JavsScript》

  1. JavaScript 中闭包无处不在,你只需要能够识别并拥抱它。
  2. 闭包是基于词法作用域书写代码时所产生的自然结果。
  3. 当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。
  4. 无论通过何种手段将内部函数传递到所在的词法作用域以外,它都会持有对原始定义作用域的引用,无论在何处执行这个函数都会使用闭包。
  5. 无论何时何地,如果将函数(访问它们各自的词法作用域)当作第一级的值类型并到处传递,你就会看到闭包在这些函数中的应用。在定时器、事件监听器、 Ajax 请求、跨窗口通信、Web Workers 或者任何其它的异步(或者同步)任务中,只要使用了回调函数,实际上就是在使用闭包。

《JavaScript编程解析》

1. 对闭包的初步认识

var fn = f();     // 将函数f 的返回值赋值给变量fn
fn(); // 1
fn(); //2
fn(); //3 function f() {
var cnt = 0;
return function() { return ++cnt; }
} var fn1 = f1();
fn1(); //1
fn1(); //1 function f1(){
var cnt = 0;
return ++cnt;
}

从表面上来看,闭包是一种具有状态的函数。或者也可以将闭包的特征理解为,其相关的局部变量在函数调用结束之后将会继续存在。

2. 闭包的原理

  1. 闭包的前提条件是需要在函数声明的内部声明另一个函数(即嵌套的函数声明)。
  2. 闭包指的是一种特殊的函数,这种函数会在被调用时保持当时的变量名查找的执行环境。
  3. 闭包仅仅是保持了变量名查找的状态,而并没有保持对象所有的状态,对此请加以区分。也就是说,闭包虽然会保持(在嵌套外层进行函数调用时被隐式地生成的)Call 对象,但无法保持 Call 对象的属性所引用的之前的对象的状态。

3. 防范命名空间的污染

  1. 模块

  2. 避免使用全局变量

  3. 通过实现信息隐藏

     //使用了闭包的模块
    // 在此调用匿名函数
    // 由于匿名函数的返回值是一个函数,所以变量sum 是一个函数
    var sum = (function() {
    // 无法从函数外部访问该名称
    // 实际上,这变成了一个私有变量
    // 一般来说,在函数被调用之后该名称就将无法再被访问
    // 不过由于是在被返回的匿名函数中,所以仍可以继续被使用
    var position = { x:2, y:3 }; // 同样是一个从函数外部无法被访问的私有变量
    // 将其命名为sum 也可以。不过为了避免混淆,这里采用其他名称
    function sum_internal(a, b) {
    return Number(a) + Number(b);
    } // 只不过是为了使用上面的两个名称而随意设计的返回值
    return function(a, b) {
    print('x = ', position.x);
    return sum_internal(a, b); };
    }
    )(); // 调用
    sum(3, 4);
    x = 2
    7

在利用函数作用域可以封装名称,以及闭包可以使名称在函数调用结束后依然存在这两个特性后,信息隐藏得以实现。

(function() { 函数体 })();

4.闭包与类

  1. 计数器功能的类

     function counter_class(init) {                  // 初始值可以通过参数设定
    var cnt = init || 0; // 设置默认参数的习惯做法(参见5.5 节) // 如有必要,可在此声明私有变量与私有函数 return {
    // 公有方法
    show:function() { print(cnt); },
    up:function() { cnt++; return this; }, // return this 在使用方法链时很方便
    down:function() { cnt--; return this; }
    };
    } // 使用代码
    var counter1 = counter_class();
    counter1.show();
    0
    counter1.up();
    counter1.show();
    1 var counter2 = counter_class(10);
    counter2.up().up().up().show(); // 方法链
    13
  2. 表达式闭包

JavaScript 有一种自带的增强功能,称为支持函数型程序设计的表达式闭包(Expression closure)。

	var sum = function(a, b) { return Number(a) + Number(b); }
//可以省略为
var sum = function(a, b) Number(a) + Number(b);

5.闭包与回调函数

《JavaScript高级程序设计》

  1. 闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数
  2. 当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链。
  3. 由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。过度使用闭包可能会导致内存占用过多,我们建议读者只在绝对必要时再考虑使用闭包。

内存泄漏

由于IE9之前的版本对JScript对象和COM对象使用不同的垃圾收集例程,因此闭包在IE的这些版本中会导致一些特殊的问题。具体来说,如果闭包的作用域链中保存着一个HTML元素,那么就意味着该元素将无法被销毁。

function assignHandler(){
var element = document.getElementById("someElement");
element.onclick = function(){
alert(element.id);
};
} //把element变量设置为null。这样就能够解除对DOM对象的引用,顺利地减少其引用数,确保正常回收其占用的内存。 function assignHandler(){
var element = document.getElementById("someElement");
var id = element.id; element.onclick = function(){
alert(id);
}; element = null;
}

《JavaScript设计模式与开发实践》

1. 闭包更多作用

  1. 封闭变量

  2. 延续局部变量的寿命

     //把img变量用闭包封闭起来,便能解决请求丢失的问题
    var report = (function(){
    var imgs = [];
    return function( src ){
    var img = new Image();
    imgs.push( img );
    img.src = src;
    }
    })();

2. 闭包与内存管理

  1. 局部变量本来应该在函数退出的时候被解除引用,但如果局部变量被封闭在闭包形成的环境中,那么这个局部变量就能一直生存下去。如果在将来需要回收这些变量,我们可以手动把这些变量设为null。
  2. 跟闭包和内存泄露有关系的地方是,使用闭包的同时比较容易形成循环引用,如果闭包的作用域链中保存着一些DOM节点,这时候就有可能造成内存泄露。但这本身并非闭包的问题,也并非JavaScript的问题。
  3. 如果要解决循环引用带来的内存泄露问题,我们只需要把循环引用中的变量设为null即可。将变量设置为null意味着切断变量与它此前引用的值之间的连接。当垃圾收集器下次运行时,就会删除这些值并回收它们占用的内存。

《JavaScript权威指南》

  1. JavaScript也采用词法作用域(lexical scoping),也就是说,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。为了实现这种词法作用域,JavaScript函数对象的内部状态不仅包含函数的代码逻辑,还必须引用当前的作用域链。函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为“闭包”。
  2. 从技术的角度讲,所有的JavaScript函数都是闭包:它们都是对象,它们都关联到作用域链。
  3. 是如果这个函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套的函数。它就不会被当做垃圾回收,并且它所指向的变量绑定对象也不会被当做垃圾回收。

转载请注明出处:http://www.cnblogs.com/givebest/p/5617565.html

JavaScript闭包(Closure)的更多相关文章

  1. 深入理解JavaScript闭包(closure)

    最近在网上查阅了不少javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Java ...

  2. [转载]学习Javascript闭包(Closure)

    学习Javascript闭包(Closure)     源地址: http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures ...

  3. javascript 闭包(closure)

    <script type="text/javascript">    //闭包(closure):内层函数可以引用存在于包围它的函数内的变量,即使外层函数的执行已经结束 ...

  4. JavaScript闭包(closure)入门: 拿"开发部"和"技术牛"举个例子

    虽然只是一小段菜鸟的学习笔记 , 不过还是希望看到的高手看到不足的时候帮忙指点~ 一:代码和执行过程 /** * http://blog.csdn.net/ruantao1989 * ==>Ju ...

  5. JavaScript闭包(二)——作用

    一.延迟调用 当在一段代码中使用 setTimeout 时,要将一个函数的引用作为它的第一个参数,而将以毫秒表示的时间值作为第二个参数. 但是,传递函数引用的同时无法为计划执行的函数提供参数.可以在代 ...

  6. JavaScript闭包(一)——实现

    闭包的官方的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 通俗点的说法是: 从理论角度:所有的函数.因为它们都在创建的时候就将上层上下文 ...

  7. JavaScript闭包——实现

    闭包的官方的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 通俗点的说法是: 从理论角度:所有的函数.因为它们都在创建的时候就将上层上下文 ...

  8. JavaScript学习总结(十六)——Javascript闭包(Closure)

    原文地址: http://www.cnblogs.com/xdp-gacl/p/3703876.html 闭包(closure)是Javascript语言的一个难点,也是它的特色, 很多高级应用都要依 ...

  9. javascript中的闭包closure详解

    目录 简介 函数中的函数 Closure闭包 使用闭包实现private方法 闭包的Scope Chain 闭包常见的问题 闭包性能的问题 总结 简介 闭包closure是javascript中一个非 ...

随机推荐

  1. windows 7(32/64位)GHO安装指南(U盘制作篇)~

    本篇接着上篇的介绍,为同学讲解U盘启动盘的制作.虽然本篇大白菜的官网上也有类似的教程,但是为了完整性,我将在这里为大家细细的讲解.在这里说一下,系统包和软件包的下载大家可以自行下载,很简单的,小主就不 ...

  2. Microsoft Azure Web Sites应用与实践【4】—— Microsoft Azure网站的“后门”

    Microsoft Azure Web Sites应用与实践 系列: [1]—— 打造你的第一个Microsoft Azure Website [2]—— 通过本地IIS 远程管理Microsoft ...

  3. DOM对象模型接口规范中的四个基本接口

    DOM对象模型的四个基本接口 在DOM对象模型接口规范中,有四个基本的接口:Document,Node,NodeList以及NamedNodeMap.在这四个基本接口中,Document接口是对文档进 ...

  4. HTML5 & CSS3初学者指南(2) – 样式化第一个网页

    介绍 我们已经使用基本的 HTML 编写了一个网页.但是,写出来的 HTML 代码的网页看起来很平淡,没有吸引力. 如何改善这种很平淡的页面呢? 让我们开始使用网页的基本样式来改善页面效果,我们将会使 ...

  5. 【MSP是什么】MSP认证之项目群管理学习心得

    学习了项目群管理后,我深受启发,在此发表下自己的一些个人感想. 项目群是指经过协调统一管理以便获取单独管理时无法取得的效益和控制的一组相互联系的项目. 项目群中的项目需要共享组织的资源, 需要进行项目 ...

  6. Atitit 多元化战略 适合我们发展 的核心业务attilax总结

    Atitit 多元化战略 适合我们发展 的核心业务attilax总结 1.1. 历史的大趋势,全球范围内人员的大流动1 1.2. 衣食住行1 1.3. 农村包围城市战略1 1.4. 挪开三座大山(住房 ...

  7. UEditor编辑器使用示例

    1. UEditor下载 UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码. 下载链接:http ...

  8. Bootstrap3系列:按钮式下拉菜单

    1. 基本实例 把按钮放入 .btn-group 中,加入适当的菜单标签,让按钮触发下拉菜单. 1.1 示例代码 <div class="btn-group"> < ...

  9. Oracle位图索引

    索引由KEY和Data组成 位图索引的KEY比普通非唯一性索引多包含一个组成部分,分区,分区是将数据按行由内部机制分段以达到比较好的检索效率 位图索引的Data中,该索引KEY中数据值在分区段中按行分 ...

  10. 初识 Sql Server存储过程

    开篇语 之前的公司并未使用存储过程来做项目,所以小生对存储过程的调用.使用也是一知半解,刚好这家公司就大量用到了存储过程 这次做的功能,为了保持风格一致,也是需要使用存储过程来实现动态sql和数据分页 ...