详解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 相关文章推荐
CLASS_CONFUSION JS混淆 全源码
Dec 12 Javascript
JQuery 无废话系列教程(一) jquery入门 [推荐]
Jun 23 Javascript
JavaScript创建一个欢迎cookie弹出窗实现代码
Mar 15 Javascript
indexOf 和 lastIndexOf 使用示例介绍
Sep 02 Javascript
JS验证IP,子网掩码,网关和MAC的方法
Jul 02 Javascript
jQuery+ajax实现实用的点赞插件代码
Jul 06 Javascript
js 判断数据类型的几种方法
Jan 13 Javascript
Bootstrap模态框使用详解
Feb 15 Javascript
javascript实现多张图片左右无缝滚动效果
Mar 22 Javascript
用ES6的class模仿Vue写一个双向绑定的示例代码
Apr 20 Javascript
详解vuex中action何时完成以及如何正确调用dispatch的思考
Jan 21 Javascript
Node.js API详解之 Error模块用法实例分析
May 14 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
Bo-Blog专用的给Windows服务器的IIS Rewrite程序
2007/08/26 PHP
PHP排序算法类实例
2015/06/17 PHP
php同时使用session和cookie来保存用户登录信息的实现代码
2016/05/13 PHP
PHP7创建COOKIE和销毁COOKIE的实例方法
2020/02/03 PHP
在textarea中屏蔽js的某个function的javascript代码
2007/04/20 Javascript
jquery随机展示头像代码
2011/12/21 Javascript
event.currentTarget与event.target的区别介绍
2012/12/31 Javascript
Javascript与jQuery方法的隐藏与显示
2015/01/19 Javascript
谈一谈javascript中继承的多种方式
2016/02/19 Javascript
node.js中 stream使用教程
2016/08/28 Javascript
聊一聊JS中的prototype
2016/09/29 Javascript
浅谈jQuery绑定事件会叠加的解决方法和心得总结
2016/10/26 Javascript
jQuery插件HighCharts实现的2D对数饼图效果示例【附demo源码下载】
2017/03/09 Javascript
详解webpack 多页面/入口支持&amp;公共组件单独打包
2017/06/29 Javascript
AngularJS 实现购物车全选反选功能
2017/10/24 Javascript
vue的无缝滚动组件vue-seamless-scroll实例
2017/12/18 Javascript
原生JS实现的简单轮播图功能【适合新手】
2018/08/17 Javascript
详解JavaScript中typeof与instanceof用法
2018/10/24 Javascript
Vue 技巧之控制父类的 slot
2020/02/24 Javascript
详解Webpack抽离第三方类库以及common解决方案
2020/03/30 Javascript
[55:25]2018DOTA2亚洲邀请赛3月29日 小组赛A组 VG VS OG
2018/03/30 DOTA
python模拟登陆阿里妈妈生成商品推广链接
2014/04/03 Python
Python文件去除注释的方法
2015/05/25 Python
用 Python 爬了爬自己的微信朋友(实例讲解)
2017/08/25 Python
python 设置输出图像的像素大小方法
2019/07/04 Python
Python爬虫获取豆瓣电影并写入excel
2020/07/31 Python
生活部的活动方案
2014/08/19 职场文书
家庭教育的心得体会
2014/09/01 职场文书
工作疏忽、懈怠的检讨书
2014/09/11 职场文书
2014向国旗敬礼网上签名活动总结
2014/09/27 职场文书
致800米运动员广播稿(10篇)
2014/10/17 职场文书
死亡诗社观后感
2015/06/05 职场文书
学雷锋广播稿大全
2015/08/19 职场文书
廉政党课工作报告案例
2019/06/21 职场文书
使用Redis做预定库存缓存功能
2022/04/02 Redis
SQL Server内存机制浅探
2022/04/06 SQL Server