转发请标明来源:http://www.cnblogs.com/johnhou/p/javascript.html  请尊重笔者的劳动成果  --John Hou

今天我们从内存结构上来讲解下 javascript中的闭包概念。

闭包:是指有权访问另外一个函数作用域中的变量的函数。创建闭包的常见方式就是在一个函数内部创建另外一个函数。

在javascript中没有块级作用域,一般为了给某个函数申明一些只有该函数才能使用的局部变量时,我们就会用到闭包,这样我们可以很大程度上减少全局作用域中的变量,净化全局作用域。

使用闭包有如上的好处,当然这样的好处是需要付出代价的,代价就是内存的占用。

如何理解上面的那句话呢?

每个函数的执行,都会创建一个与该函数相关的函数执行环境,或者说是函数执行上下文。这个执行上下文中有一个属性 scope chain(作用域链指针),这个指针指向一个作用域链结构,作用域链中的指针又都指向各个作用域对应的活动对象。正常情况,一个函数在调用开始执行时创建这个函数执行上下文及相应的作用域链,在函数执行结束后释放函数执行上下文及相应作用域链所占的空间。

比如:

//声明函数

function test(){

var str = "hello world";

console.log(str);

}

//调用函数

test();

在调用函数的时候会在内存中生成如下图的结构:

但是闭包的情况就有点特殊了,由于闭包函数可以访问外层函数中的变量,所以外层函数在执行结束后,其作用域活动对象并不会被释放(注意,外层函数执行结束后执行环境和对应的作用域链就会被销毁),而是被闭包函数的作用域链所引用,直到闭包函数被销毁后,外层函数的作用域活动对象才会被销毁。这也正是闭包要占用内存的原因。

所以使用闭包有好处,也有坏处,滥用闭包会造成内存的大量消耗。

使用闭包还有其他的副作用,可以说是bug,也可以说不是,相对不同的业务可能就会有不同的看法。

这个副作用是 闭包函数只能取到外层函数变量的最终值。

测试代码如下:(这里使用了jquery对象)

/*闭包缺陷*/

(function($){

var result = new Array(),

i = 0;

for(;i<10;i++){

result[i] = function(){

return i;

};

}

$.RES1 = result;

})(jQuery);

// 执行数组中的函数

$.RES1[0]();

上面的代码先通过匿名函数表达式开辟了一块私有作用域,这个匿名函数就是我们上面所说的外层函数,该外层函数有一个参数$,同时还定义了变量result 和 I , 通过for循环给数组result赋值一个匿名函数,这个匿名函数就是闭包,他访问了外层函数的变量I , 理论上数组result[i]() 会返回相应的数组下标值,实际情况却不如所愿。

如上代码 $.RES1[0]() 的执行结果是10.

为什么会这样呢,因为i的最终值就是10.

下面我们通过下图来详细说明下,上面的那段代码执行时在内存中到底发生了什么:

那么这个副作用有没有办法可以修复呢?当然可以!

我们可以通过下面的代码来达到我们的预期。

/*修复闭包缺陷*/

(function($){

var result = new Array(),

i = 0;

for(;i<10;i++){

result[i] = function(num){

return function(){

return num;

}

}(i);

}

$.RES2 = result;

})(jQuery);

//调用闭包函数

console.log($.RES2[0]());

上面的代码又在内存中发生了什么?我们同样用下面的一幅图来详细解释。看懂了上面的图,我们也就不难理解下面的图。

以下是我的微信公众号,技术大牛集结号,欢迎您的关注!

给我足够的时间,我能模拟整个世界!

javascript系列2 -- 闭包详解的更多相关文章

  1. javaScript系列:JSON详解

    JSON详解   JSON的全称是”JavaScript Object Notation”,意思是JavaScript对象表示法,它是一种基于文本,独立于语言的轻量级数据交换格式.XML也是一种数据交 ...

  2. JavaScript中的闭包详解

    闭包是JavaScript的重要特性,非常强大,可用于执行复杂的计算,可并不容易理解,尤其是对之前从事面向对象编程的人来说,对 JavaScript 认识和编程显得更难.特别是在看一些开源的JavaS ...

  3. JavaScript系列文章:详解正则表达式之一

    正则表达式是一个精巧的利器,经常用来在字符串中查找和替换,JavaScript语言参照Perl,也提供了正则表达式相关模块,开发当中非常实用,在一些类库或是框架中,比如jQuery,就存在大量的正则表 ...

  4. JavaScript系列文章:详解正则表达式之三

    在上两篇文章中博主介绍了JavaScript中的正则常用方法和正则修饰符,今天准备聊一聊元字符和高级匹配的相关内容. 首先说说元字符,想必大家也都比较熟悉了,JS中的元字符有以下几种: / \ | . ...

  5. JavaScript系列----AJAX机制详解以及跨域通信

    1.Ajax 1.1.Ajax简介 Ajax简介这一部分我们主要是谈一下ajax的起源,ajax是什么?因为这些是跟技术无关的.所以,大多细节都是一笔带过. Ajax的起源? Ajax一词源于2005 ...

  6. JavaScript系列文章:详解正则表达式之二

    在上一篇文章中我们讲了正则表达式的基本用法,接下来博主想聊聊其中的细节,今天就从正则修饰符开始吧. 正则修饰符又称为正则标记(flags),它会对正则的匹配规则做限定,进而影响匹配的最终结果.在上次的 ...

  7. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  8. (转)javascript中event对象详解

    原文:http://jiajiale.iteye.com/blog/195906 javascript中event对象详解          博客分类: javaScript JavaScriptCS ...

  9. Javascript 异步加载详解

    Javascript 异步加载详解 本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy ...

随机推荐

  1. Linux - test测试标志的意思总结

    测试的标志 代表意义 1. 关於某个档名的『文件类型』判断,如 test -e filename 表示存在否 -e 该『档名』是否存在?(常用) -f 该『档名』是否存在且为文件(file)?(常用) ...

  2. 有关java的引用传递,直接操作对象本身。直接删除BE的value中某值

    HashSet<String> refRegions = BE.get(regionName);    HashSet<String> values = new HashSet ...

  3. iOS下FMDB的多线程操作(二)

    上一篇记录不使用FMDatabaseQueue来使用多线程,这一篇记录一下使用FMDatabaseQueue的方式. 需要注意的时queue操作中不能嵌套queue操作,否则会各种错误. 当使用FMD ...

  4. Android 客户端与服务器交互

    在android中有时候我们不需要用到本机的SQLite数据库提供数据,更多的时候是从网络上获取数据,那么Android怎么从服务器端获取数据呢?有很多种,归纳起来有 一:基于Http协议获取数据方法 ...

  5. 关于ARC的介绍和ARC与MRC混编解决

    1. ARC & MRC 混合开发 在项目开发中,遇到使用MRC开发的第三方库怎么办? 例如:ASI 1> 尝试使用Xcode的转换工具(失败率比较高) 2> 在编译选项中,为MR ...

  6. OVS 中的哈希表: shash

    shash出现在OVS的代码中,定义如下:   struct hmap_node {     size_t hash;     struct hmap_node * next; };   struct ...

  7. subsets(子集)

    Given a set of distinct integers, nums, return all possible subsets (the power set). Note: The solut ...

  8. unity零基础开始学习做游戏(二)让你的对象动起来

    -------小基原创,转载请给我一个面子 小基认为电子游戏与电影最重要的区别就是交互,如果电子游戏没有让你输入的交互功能的话,全程都"只可远观,而不可鼓捣"的话,你可能是在看视频 ...

  9. (转)java之Spring(IOC)注解装配Bean详解

    java之Spring(IOC)注解装配Bean详解   在这里我们要详细说明一下利用Annotation-注解来装配Bean. 因为如果你学会了注解,你就再也不愿意去手动配置xml文件了,下面就看看 ...

  10. HTML编码和CSS编码会遇到的问

    http://codeguide.bootcss.com/#html-syntax  参考链接 属性顺序 HTML 属性应当按照以下给出的顺序依次排列,确保代码的易读性. class id, name ...