详解js闭包


Posted in Javascript onSeptember 02, 2014

闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

闭包有三个特性:

1.函数嵌套函数
2.函数内部可以引用外部的参数和变量
3.参数和变量不会被垃圾回收机制回收
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量

使用闭包有一个优点,也是它的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量。全局变量在每个模块都可调用,这势必将是灾难性的。

所以推荐使用私有的,封装的局部变量。

一般函数执行完毕后,局部活动对象就被销毁,,内存中仅仅保存全局作用域。但闭包的情况不同!

嵌套函数的闭包:

function aaa() { 
     var a = 1; 
     return function(){
      alert(a++)
     }; 
    }     
    var fun = aaa(); 
    fun();// 1 执行后 a++,,然后a还在~ 
    fun();// 2  
    fun = null;//a被回收!!

 
以上输出结果为5;
闭包会使变量始终保存在内存中,如果不当使用会增大内存消耗。

javascript的垃圾回收原理

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

那么使用闭包有什么好处呢?使用闭包的好处是:

1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在
一、全局变量的累加

<script>
var a = 1;
function abc(){
    a++;
    alert(a);
}
abc();       //2
abc();      //3
</script>

二、局部变量
<script>

function abc(){
    var a = 1;
    a++;
    alert(a);
}
abc();            //2
abc();          //2
</script>

那么怎么才能做到变量a既是局部变量又可以累加呢?

三、局部变量的累加(闭包所能做到的)

<script>
function outer(){
    var x=10;
    return function(){       //函数嵌套函数
        x++;
        alert(x);
    }
}
var y = outer();       //外部函数赋给变量y;
y();         //y函数调用一次,结果为11
y();        //y函数调用第二次,结果为12,实现了累加
</script>

js中的函数声明与函数表达式:
在js中我们可以通过关键字function来声明一个函数:

<script>
function abc(){
    alert(123);
}
abc();
</script>

我们也可以通过一个"()"来将这个声明变成一个表达式:

<script>
(function (){
    alert(123);
})();          //然后通过()直接调用前面的表达式即可,因此函数可以不必写名字;
</script>

四、模块化代码,减少全局变量的污染

<script>
var abc = (function(){   //abc为外部匿名函数的返回值
    var a = 1;
    return function(){
        a++;
        alert(a);
    }
})();
abc();  //2 ;调用一次abc函数,其实是调用里面内部函数的返回值  
abc();  //3
</script>

五、私有成员的存在

<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>

六、在循环中直接找到对应元素的索引

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
      <title></title>
  <script>
  window.onload = function(){
      var aLi = document.getElementsByTagName('li');
      for (var i=0;i<aLi.length;i++){
          aLi[i].onclick = function(){    //当点击时for循环已经结束
          alert(i);
          };
      }
  }
  </script>

  </head>
  <body>
      <ul>
          <li>123</li>
          <li>456</li>
          <li>789</li>
          <li>010</li>
      </ul>
  </body>
  </html>

七、使用闭包改写上面代码:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" />
      <title></title>
  <script>
  window.onload = function(){
      var aLi = document.getElementsByTagName('li');
      for (var i=0;i<aLi.length;i++){
          (function(i){
              aLi[i].onclick = function(){
                  alert(i);
              };
          })(i);
      }
      };
  </script>

  </head>
  <body>
      <ul>
          <li>123</li>
          <li>456</li>
          <li>789</li>
      </ul>
  </body>
  </html>
Javascript 相关文章推荐
ext 同步和异步示例代码
Sep 18 Javascript
用JavaScript对JSON进行模式匹配 (Part 2 - 实现)
Jul 17 Javascript
基于Jquery的表格隔行换色,移动换色,点击换色插件
Dec 22 Javascript
js获取本机的外网/广域网ip地址完整源码
Aug 12 Javascript
JS Replace 全部替换字符的用法小结
Dec 24 Javascript
jquery实现保存已选用户
Jul 21 Javascript
javascript实现拖放效果
Dec 16 Javascript
jquery实现下拉框左右选择功能
Feb 21 Javascript
jQuery插件HighCharts实现气泡图效果示例【附demo源码】
Mar 13 Javascript
浅谈JsonObject中的key-value数据解析排序问题
Dec 06 Javascript
JavaScript生成一个不重复的ID的方法示例
Sep 16 Javascript
小程序使用分包的示例代码
Mar 23 Javascript
jquery delay()介绍及使用指南
Sep 02 #Javascript
使用jquery实现放大镜效果
Sep 02 #Javascript
javascript初学者常用技巧
Sep 02 #Javascript
js/jquery判断浏览器的方法小结
Sep 02 #Javascript
Iframe实现跨浏览器自适应高度解决方法
Sep 02 #Javascript
jQuery级联操作绑定事件实例
Sep 02 #Javascript
jquery和css3实现的炫酷时尚的菜单导航
Sep 01 #Javascript
You might like
虚拟主机中对PHP的特殊设置
2006/10/09 PHP
ThinkPHP CURD方法之page方法详解
2014/06/18 PHP
PHP批量修改文件名称的方法分析
2017/02/27 PHP
PHP常用header头定义代码示例汇总
2020/08/29 PHP
JS子父窗口互相操作取值赋值的方法介绍
2013/05/11 Javascript
JS的location.href跳出框架打开新页面的方法
2014/09/04 Javascript
JS实现向表格中动态添加行的方法
2015/03/30 Javascript
原生javascript实现匀速运动动画效果
2016/02/26 Javascript
vue-cli+webpack记事本项目创建
2017/04/01 Javascript
vue3.0 CLI - 2.6 - 组件的复用入门教程
2018/09/14 Javascript
微信小程序实现的点击按钮 弹出底部上拉菜单功能示例
2018/12/20 Javascript
Vue实现简单分页器
2018/12/29 Javascript
微信小程序 (地址选择1)--选取搜索地点并显示效果
2019/12/17 Javascript
[02:05]DOTA2完美大师赛趣味视频之看我表演
2017/11/18 DOTA
[01:04:14]OG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
在Python中输入一个以空格为间隔的数组方法
2018/11/13 Python
python直接获取API传递回来的参数方法
2018/12/17 Python
对Python3之进程池与回调函数的实例详解
2019/01/22 Python
几个适合python初学者的简单小程序,看完受益匪浅!(推荐)
2019/04/16 Python
如何把外网python虚拟环境迁移到内网
2020/05/18 Python
使用Django搭建网站实现商品分页功能
2020/05/22 Python
python中tab键是什么意思
2020/06/18 Python
利用CSS3实现开门效果实例源码
2016/08/22 HTML / CSS
来自美国主售篮球鞋的零售商店:KICKSUSA
2017/11/28 全球购物
英国最大的纸工艺品商店:CraftStash
2018/12/01 全球购物
澳洲CFL商城:CHEMIST FOR LESS(中文)
2021/02/28 全球购物
益模软件Java笔试题
2012/03/27 面试题
酒店管理专业学生求职信
2013/09/27 职场文书
自我评价正确写法范文
2013/12/10 职场文书
六年级数学教学反思
2014/02/03 职场文书
四风存在的原因分析
2014/02/11 职场文书
《风筝》教学反思
2014/04/10 职场文书
喝酒驾驶检讨书
2014/10/01 职场文书
观后感格式
2015/06/19 职场文书
小学四年级班务总结该怎么写?
2019/08/16 职场文书
Python GUI编程之tkinter 关于 ttkbootstrap 的使用详解
2022/03/03 Python