详解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 相关文章推荐
Jquery Ajax学习实例3 向WebService发出请求,调用方法返回数据
Mar 16 Javascript
EXTJS FORM HIDDEN TEXTFIELD 赋值 使用value不好用的问题
Apr 16 Javascript
javascript的创建多行字符串的7种方法
Apr 29 Javascript
浅谈JavaScript函数节流
Dec 09 Javascript
jquery判断至少有一个checkbox被选中的方法
Jun 05 Javascript
JavaScript中的toLocaleLowerCase()方法使用详解
Jun 06 Javascript
详解Angularjs在控制器(controller.js)中使用过滤器($filter)格式化日期/时间实例
Feb 17 Javascript
JS实现基于Sketch.js模拟成群游动的蝌蚪运动动画效果【附demo源码下载】
Aug 18 Javascript
node中使用log4js4.x版本记录日志的方法
Aug 20 Javascript
vue中组件通信详解(父子组件, 爷孙组件, 兄弟组件)
Jul 27 Javascript
vue+canvas实现拼图小游戏
Sep 18 Javascript
JavaScript 绘制饼图的示例
Feb 19 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中让人头疼的浮点数运算分析
2016/10/10 PHP
Laravel 5.5 的自定义验证对象/类示例代码详解
2017/08/29 PHP
jquery 框架使用教程 AJAX篇
2009/10/11 Javascript
用Javascript同时提交多个Web表单的方法
2009/12/26 Javascript
jQuery中用dom操作替代正则表达式
2014/12/29 Javascript
Javascript中数组sort和reverse用法分析
2014/12/30 Javascript
JS控制表格实现一条光线流动分割行的方法
2015/03/09 Javascript
在JavaScript中使用NaN值的方法
2015/06/05 Javascript
JavaScript的jQuery库插件的简要开发指南
2015/08/12 Javascript
Javascript编程之继承实例汇总
2015/11/28 Javascript
快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)
2016/08/29 Javascript
JavaScript中校验银行卡号的实现代码
2016/12/19 Javascript
node.js 中间件express-session使用详解
2017/05/20 Javascript
微信小程序 地图map实例详解
2017/06/07 Javascript
vue组件编写之todolist组件实例详解
2018/01/22 Javascript
利用Blob进行文件上传的完整步骤
2018/08/02 Javascript
jQuery pjax 应用简单示例
2018/09/20 jQuery
Vue项目服务器部署之子目录部署方法
2019/05/12 Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
2020/05/08 Javascript
在vue项目中引用Antv G2,以饼图为例讲解
2020/10/28 Javascript
使用Python对Excel进行读写操作
2017/03/30 Python
实例讲解Python爬取网页数据
2018/07/08 Python
Python实战购物车项目的实现参考
2019/02/20 Python
python利用selenium进行浏览器爬虫
2019/04/25 Python
python sorted函数的小练习及解答
2019/09/18 Python
Python求解排列中的逆序数个数实例
2020/05/03 Python
python 爬取小说并下载的示例
2020/12/07 Python
Born鞋子官网:Born Shoes
2017/04/06 全球购物
数据库连接池的工作原理
2012/09/26 面试题
共产党员公开承诺书范文
2014/03/28 职场文书
大学生入党积极分子自我评价
2014/09/20 职场文书
2014年助理工程师工作总结
2014/11/14 职场文书
2015年大学班主任工作总结
2015/04/30 职场文书
企业文化学习心得体会
2016/01/21 职场文书
python执行js代码的方法
2021/05/13 Python
海贼王十大逆天果实 魂魂果实上榜,岩浆果实攻击力最强
2022/03/18 日漫