林炳文Evankaka原创作品。转载请注明出处http://blog.csdn.net/evankaka
           摘要:本文主要讲了JavaScript闭包的原理、特点并用一些实例做了证明

一、闭包的概念与好处

1.1、什么是闭包?
闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

闭包的特点:
  1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
  2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
  简单的说,Javascript允许使用内部函数---即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。

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

1.2、javascript的垃圾回收原理

1.在javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收;
2.如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。

1.3、使用闭包的好处

那么使用闭包有什么好处呢?使用闭包的好处是:
1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在

二、实例讲解

内部函数

让我们从一些基础的知识谈起,首先了解一下内部函数。内部函数就是定义在另一个函数中的函数。例如:

function outerFn () {functioninnerFn () {}
}

innerFn就是一个被包在outerFn作用域中的内部函数。这意味着,在outerFn内部调用innerFn是有效的,而在outerFn外部调用innerFn则是无效的。

当function里嵌套function时,内部的function可以访问外部function里的变量。

如下:

<!DOCTYPE html>
<meta charset="utf-8" />
<html>
<head>
</head>
<body><button οnclick="fun()">请点击这里</button><script>function fun(){outfun(1);}function outfun(x) { var tmp = 1; function infun(y) { alert(x + y + (++tmp)); } infun(10); } </script>
</body>
</html>

输出结果;


不管执行多少次,都会alert 13,因为infun能访问outfun的参数x,也能访问outfun的变量tmp。但,这还不是闭包。当你return的是内部function时,就是一个闭包。内部function会close-over外部function的变量直到内部function结束。

将函数更改成如下就是闭包了:

<!DOCTYPE html>
<meta charset="utf-8" />
<html>
<head>
</head>
<body><button οnclick="fun()">请点击这里</button><script>var test =  outfun(1);function fun(){              test(10);}function outfun(x) { var tmp = 1; return  function infun(y) { alert(x + y + (++tmp)); } //这样才是闭包} </script>
</body>
</html>

这里每次点击后结果都会加1

第一次点:

第二次点:

当然, 我们也可以使用全局变量来调用闭包

再来看一个例子

 function f1(){var n=999;nAdd=function(){n+=1}//所有的变量,如果不加上var关键字,则默认的会添加到全局对象的属性上去function f2(){alert(n);}return f2;}var result=f1();result(); // 999nAdd();result(); // 1000

    在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
    为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
      这段代码中另一个值得注意的地方,就是“nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此 nAdd是一个全局变量,而不是局部变量。其次,nAdd  的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

JavaScript中所有的function都是一个闭包。不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”。看下面这段代码:

function a() {
var i = 0;
function b() { alert(++i); }
return b;
}
var c = a();
c();

这样在执行完var c=a()后,变量c实际上是指向了函数b,再执行c()后就会弹出一个窗口显示i的值(第一次为1)。这段代码其实就创建了一个闭包,为什么?因为函数a外的变量c引用了函数a内的函数b,就是说:当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。

看完了上面,闭包其实在json中也可以来使用,这种方法在很多框架中还经常见到,最基础如下:

<script>
var aaa = (function(){var a = 1;function bbb(){a++;alert(a);}function ccc(){a++;alert(a);}return {b:bbb,             //json结构c:ccc}
})();
aaa.b();     //2
aaa.c()      //3
</script>

这里使用了json,返回是一个json

我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,

那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。

var CachedSearchBox = (function(){
var cache = {},
count = [];
return {
attachSearchBox : function(dsid){
if(dsid in cache){//如果结果在缓存中
return cache[dsid];//直接返回缓存中的对象
}
var fsb = new uikit.webctrl.SearchBox(dsid);//新建
cache[dsid] = fsb;//更新缓存
if(count.length > 100){//保正缓存的大小<=100
delete cache[count.shift()];
}
return fsb;
}, clearSearchBox : function(dsid){
if(dsid in cache){
cache[dsid].clearSelection();
}
}
};
})(); CachedSearchBox.attachSearchBox("input"); 

这样我们在第二次调用的时候,就会从缓存中读取到该对象,如果上面的例子看不懂,那就看下面的吧

var db = (function() {
// 创建一个隐藏的object, 这个object持有一些数据
// 从外部是不能访问这个object的
var data = {};
// 创建一个函数, 这个函数提供一些访问data的数据的方法
return function(key, val) {if (val === undefined) { return data[key] } // getelse { return data[key] = val } // set}
// 我们可以调用这个匿名方法
// 返回这个内部函数,它是一个闭包
})();db('x'); // 返回 undefined
db('x', 1); // 设置data['x']为1
db('x'); // 返回 1
// 我们不可能访问data这个object本身
// 但是我们可以设置它的成员

三、使用闭包的注意点

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便
改变父函数内部变量的值。

JavaScript闭包研究相关推荐

  1. JavaScript闭包如何工作?

    您将如何向了解其闭包概念(例如函数,变量等)的人解释JavaScript闭包,但却不了解闭包本身? 我已经在Wikipedia上看到了Scheme示例 ,但是不幸的是它没有帮助. #1楼 我知道已经有 ...

  2. JavaScript闭包的底层运行机制

    转自:http://blog.leapoahead.com/2015/09/15/js-closure/ 我研究JavaScript闭包(closure)已经有一段时间了.我之前只是学会了如何使用它们 ...

  3. javascript 闭包_了解JavaScript闭包:实用方法

    javascript 闭包 Learning a new language involves a series of steps, whereas its mastery is a product o ...

  4. Javascript闭包和闭包的几种写法及用途

    好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一些实用的东西,主要将闭包的写法.用法和用途.  一.什么 ...

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

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什 ...

  6. 全面理解Javascript闭包和闭包的几种写法及用途【转】

    一.什么是闭包和闭包的几种写法和用法 1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. ...

  7. 全面理解Javascript闭包和闭包的几种写法及用途

     一.什么是闭包和闭包的几种写法和用法 1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. ...

  8. 让你分分钟理解 JavaScript 闭包

    原文:https://www.cnblogs.com/onepixel/p/5062456.html 让你分分钟理解 JavaScript 闭包 闭包,是 Javascript 比较重要的一个概念,对 ...

  9. 全面理解Javascript闭包和闭包的几种写法及用途--转载自https://www.cnblogs.com/yunfeifei/p/4019504.html...

    全面理解Javascript闭包和闭包的几种写法及用途 好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一 ...

最新文章

  1. document.getElementById vs jQuery $()
  2. 算法与数据结构(面向对象思想)
  3. 结对开发Ⅴ——循环一维数组求和最大的子数组
  4. 九章算法强化班 - 课程大纲
  5. matlab变压器损耗仿真,基于Matlab的变压器运行特性仿真专题报告.docx
  6. 概要设计说明书_没有什么比牙签更好的设计了
  7. html5新加入的内容,10个html5增加的重要新特性和内容
  8. oracle学习笔记(十三) 查询练习(三) 子查询查询
  9. 阿里开发规范_字字珠玑,高级技术专家带你了解阿里的开发流程规范
  10. 牛掰!某厂风控大佬整理的一套黑客学习思维导图及教程!
  11. Windows socket测试工具
  12. css基础--border属性
  13. JAVA8实战 -- Lamdba表达式
  14. Q3营收利润双降,新作将成Take-Two逆势大爆发的动力?
  15. ubuntu14.04 64位安装H3C iNode客户端
  16. 4天4夜渡劫成功,解决10月1项目上线遇到的一个Mysql大坑,导致项目无法正常访问
  17. HTML5+CSS3小实例:后台管理系统的侧边导航栏
  18. 自定义类加载器加载冲突类(一)-ClassLoader
  19. Mac扫描局域网内连接设备IP及MAC地址并查看对应IP开放端口
  20. Java中类型zhaun‘huan

热门文章

  1. d3.js环形统计图代码
  2. 各纬度气候分布图_气候气压带图_世界气候气压带风带分布图要图(需要表识纬度)-4d影院专题信息栏目...
  3. UVA 12235 Help Bubu
  4. 国产电脑支持Linux吗,天玥计算机(电脑)支持UOS、银河麒麟、Deepin等国产操作系统...
  5. html本地化软件,如何为本地化做准备 (HTML)
  6. 计算机与昆虫关系的论文,浅谈昆虫与人类的关系.doc
  7. 无线网络CSMA/CA原理分析以及相关技术的介绍和分析
  8. 数据可视化设计师必备的图表规范指南
  9. Win10+YOLOv5运行记录
  10. 20175208 张家华 MyCP