详解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 相关文章推荐
Prototype 学习 工具函数学习($A方法)
Jul 12 Javascript
ExtJs Excel导出并下载IIS服务器端遇到的问题
Sep 16 Javascript
一个js控制的导航菜单实例代码
Dec 03 Javascript
js脚本获取webform服务器控件的方法
May 16 Javascript
javascript结合CSS实现苹果开关按钮特效
Apr 07 Javascript
基于JS实现Android,iOS一个手势动画效果
Apr 27 Javascript
AngularJs Forms详解及简单示例
Sep 01 Javascript
详解jQuery插件开发方式
Nov 22 Javascript
Angularjs之filter过滤器(推荐)
Nov 27 Javascript
JS实现把一个页面层数据传递到另一个页面的两种方式
Aug 13 Javascript
解决Vue中使用keepAlive不缓存问题
Aug 04 Javascript
浅谈JavaScript节流和防抖函数
Aug 25 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使之能同时支持GIF和JPEG
2006/10/09 PHP
实用函数10
2007/11/08 PHP
PHP的substr_replace将指定两位置之间的字符替换为*号
2011/05/04 PHP
PHP实现的MongoDB数据库操作类分享
2014/05/12 PHP
PHP整合七牛实现上传文件
2015/07/03 PHP
PHP之预定义接口详解
2015/07/29 PHP
laravel-admin的多级联动方法
2019/09/30 PHP
thinkphp 5框架实现登陆,登出及session登陆状态检测功能示例
2019/10/10 PHP
TP5框架安全机制实例分析
2020/04/05 PHP
用js来解决ajax读取页面乱码
2010/11/28 Javascript
js模拟滚动条(横向竖向)
2013/02/22 Javascript
Javascript中Array.prototype.map()详解
2014/10/22 Javascript
JavaScript使用Replace进行字符串替换的方法
2015/04/14 Javascript
用headjs来管理和加载js 提高网站加载速度
2016/11/29 Javascript
AngularJS双向绑定和依赖反转实例详解
2017/04/15 Javascript
javascript 取小数点后几位几种方法总结
2017/08/02 Javascript
vue webuploader 文件上传组件开发
2017/09/23 Javascript
vue-resource拦截器设置头信息的实例
2017/10/27 Javascript
JavaScript数据结构与算法之队列原理与用法实例详解
2017/11/22 Javascript
JavaScript数组去重的几种方法
2019/04/07 Javascript
Vue实现页面添加水印功能
2019/11/09 Javascript
跟老齐学Python之有容乃大的list(1)
2014/09/14 Python
Python fileinput模块使用实例
2015/06/03 Python
python编程实现12306的一个小爬虫实例
2017/12/27 Python
JSON文件及Python对JSON文件的读写操作
2018/10/07 Python
利用python-docx模块写批量生日邀请函
2019/08/26 Python
Python 格式化打印json数据方法(展开状态)
2020/02/27 Python
Python如何用filter函数筛选数据
2020/03/05 Python
Tensorflow卷积实现原理+手写python代码实现卷积教程
2020/05/22 Python
在 Python 中使用 7zip 备份文件的操作
2020/12/11 Python
Python 中 sorted 如何自定义比较逻辑
2021/02/02 Python
HTML5标签使用方法详解
2015/11/27 HTML / CSS
美国最大的香水连锁店官网:Perfumania
2016/08/15 全球购物
医学专业大学生求职的自我评价
2013/11/27 职场文书
python基于opencv批量生成验证码的示例
2021/04/28 Python
python神经网络学习 使用Keras进行回归运算
2022/05/04 Python