详解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遍历页面所有CheckBox查看是否被选中的方法
Apr 14 Javascript
JavaScript正则表达式之multiline属性的应用
Jun 16 Javascript
jquery siblings获取同辈元素用法实例分析
Jul 25 Javascript
jQuery获取与设置iframe高度的方法
Aug 01 Javascript
Angular 2应用的8个主要构造块有哪些
Oct 17 Javascript
Node.js的Mongodb使用实例
Dec 30 Javascript
JS弹窗 JS弹出DIV并使整个页面背景变暗功能的实现代码
Apr 21 Javascript
vue webpack开发访问后台接口全局配置的方法
Sep 18 Javascript
jquery拖拽自动排序插件使用方法详解
Jul 20 jQuery
详解Vue底部导航栏组件
May 02 Javascript
javascript sort()对数组中的元素进行排序详解
Oct 13 Javascript
微信小程序实现登录注册功能
Dec 29 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
ThinkPHP3.1的Widget新用法
2014/06/19 PHP
什么情况下可以不写PHP的闭合标签“?&gt;”
2014/08/28 PHP
javascript中的undefined和not defined区别示例介绍
2014/02/26 Javascript
JavaScript实现向右伸出的多级网页菜单效果
2015/08/25 Javascript
JS+CSS实现另类带提示效果的竖向导航菜单
2015/10/15 Javascript
浅谈Nodejs应用主文件index.js
2016/08/28 NodeJs
jQuery的deferred对象使用详解
2016/09/25 Javascript
vue.js中$watch的用法示例
2016/10/04 Javascript
Bootstrap select下拉联动(jQuery cxselect)
2017/01/04 Javascript
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
2020/10/26 Javascript
判断横屏竖屏(三种)
2017/02/13 Javascript
说说node中的可读流和可写流的区别
2018/06/01 Javascript
Node.js中的cluster模块深入解读
2018/06/11 Javascript
Vue无限滑动周选择日期的组件的示例代码
2018/07/18 Javascript
JavaScript类的继承操作实例总结
2018/12/20 Javascript
layui switch 开关监听 弹出确定状态转换的例子
2019/09/21 Javascript
es6函数name属性功能与用法实例分析
2020/04/18 Javascript
基于Vue2实现移动端图片上传、压缩、拖拽排序、拖拽删除功能
2021/01/05 Vue.js
Javascript中的奇葩知识,你知道吗?
2021/01/25 Javascript
python使用百度翻译进行中翻英示例
2014/04/14 Python
Python中捕捉详细异常信息的代码示例
2014/09/18 Python
Python3使用requests发闪存的方法
2016/05/11 Python
利用Python脚本生成sitemap.xml的实现方法
2017/01/31 Python
Python3.6简单反射操作示例
2018/06/14 Python
详解Django+Uwsgi+Nginx 实现生产环境部署
2018/11/06 Python
python与mysql数据库交互的实现
2020/01/06 Python
如何配置关联Python 解释器 Anaconda的教程(图解)
2020/04/30 Python
python opencv实现简易画图板
2020/08/27 Python
密封类可以有虚函数吗
2014/08/11 面试题
中学教师培训制度
2014/01/31 职场文书
客服部工作职责范本
2014/02/14 职场文书
破坏寝室公物检讨书
2014/11/17 职场文书
检讨书范文
2015/01/27 职场文书
关于观后感的作文
2015/06/18 职场文书
高中升旗仪式主持词
2015/07/03 职场文书
mongoDB数据库索引快速入门指南
2022/03/23 MongoDB