详解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 相关文章推荐
输入密码检测大写是否锁定js实现代码
Dec 03 Javascript
详解JS面向对象编程
Jan 24 Javascript
javascript与jquery动态创建html元素示例
Jul 25 Javascript
基于AngularJS实现iOS8自带的计算器
Sep 12 Javascript
js实现简单的获取验证码按钮效果
Mar 03 Javascript
完美解决UI-Grid表格元素中多个空格显示为一个空格的问题
Apr 25 Javascript
Form表单上传文件(type=&quot;file&quot;)的使用
Aug 03 Javascript
解决Linux无法正常安装与卸载Node.js的方法
Jan 19 Javascript
Vue微信项目按需授权登录策略实践思路详解
May 07 Javascript
详解webpack打包后如何调试的方法步骤
Nov 07 Javascript
vue router总结 $router和$route及router与 router与route区别
Jul 05 Javascript
ES6函数和数组用法实例分析
May 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使用ereg验证文件上传的方法
2014/12/16 PHP
PHP获取POST数据的几种方法汇总
2015/03/03 PHP
学习php设计模式 php实现桥梁模式(bridge)
2015/12/07 PHP
php操作access数据库的方法详解
2017/02/22 PHP
php识别翻转iphone拍摄的颠倒图片
2018/05/17 PHP
laravel入门知识点整理
2020/09/15 PHP
Alliance vs AM BO3 第二场2.13
2021/03/10 DOTA
jquery动画3.创建一个带遮罩效果的图片走廊
2012/08/24 Javascript
jQuery语法总结和注意事项小结
2012/11/11 Javascript
jQuery获取(选中)单选,复选框,下拉框中的值
2014/02/21 Javascript
jquery实现邮箱自动填充提示功能
2015/11/17 Javascript
node.js+express制作网页计算器
2016/01/17 Javascript
基于canvas实现的钟摆效果完整实例
2016/01/26 Javascript
简单的分页代码js实现
2016/05/17 Javascript
json传值以及ajax接收详解
2016/05/24 Javascript
jQuery实现倒计时重新发送短信验证码功能示例
2017/01/12 Javascript
详解Angular6.0使用路由步骤(共7步)
2018/06/29 Javascript
使用JS实现导航切换时高亮显示的示例讲解
2018/08/22 Javascript
vue el-table实现自定义表头
2019/12/11 Javascript
js面向对象之实现淘宝放大镜
2020/01/15 Javascript
python计算书页码的统计数字问题实例
2014/09/26 Python
python统计字符串中指定字符出现次数的方法
2015/04/04 Python
Python程序员面试题 你必须提前准备!(答案及解析)
2018/01/23 Python
Django项目后台不挂断运行的方法
2019/08/31 Python
python统计函数库scipy.stats的用法解析
2020/02/25 Python
实例讲解Python 迭代器与生成器
2020/07/08 Python
英国最好的温室之家:Greenhouses Direct
2019/07/13 全球购物
仓管岗位职责范本
2014/02/08 职场文书
2015年事业单位工作总结
2015/04/27 职场文书
舌尖上的中国观后感
2015/06/02 职场文书
海底两万里读书笔记
2015/06/26 职场文书
嘉年华活动新闻稿
2015/07/17 职场文书
好人好事新闻稿
2015/07/17 职场文书
课文《燕子》教学反思
2016/02/17 职场文书
Java新手教程之ArrayList的基本使用
2021/06/20 Java/Android
《仙剑客栈2》第一弹正式宣传片公开 年内发售
2022/04/07 其他游戏