详解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 tips提示效果
Apr 03 Javascript
一个挺有意思的Javascript小问题说明
Sep 26 Javascript
BootStrap中Datetimepicker和uploadify插件应用实例小结
May 26 Javascript
基于JavaScript代码实现自动生成表格
Jun 15 Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
Jun 23 Javascript
jQuery中text() val()和html()的区别实例详解
Jun 28 Javascript
jQuery 如何实现一个滑动按钮开关
Dec 01 Javascript
JavaScript实现左侧菜单效果
Dec 14 Javascript
完美解决axios跨域请求出错的问题
Feb 05 Javascript
json数据传到前台并解析展示成列表的方法
Aug 06 Javascript
微信小程序实现即时通信聊天功能的实例代码
Aug 17 Javascript
使用 UniApp 实现小程序的微信登录功能
Jun 09 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
超神学院:天使彦公认最美的三个视角,网友:我的天使快下凡吧!
2020/03/02 国漫
Yii学习总结之数据访问对象 (DAO)
2015/02/22 PHP
UPUPW 更新 64 位 Apache 系列 PHP 7.0 正式版
2015/12/08 PHP
PHP中类的自动加载的方法
2017/03/17 PHP
yii 2.0中表单小部件的使用方法示例
2017/05/23 PHP
Kindeditor编辑器添加图片上传水印功能(php代码)
2017/08/03 PHP
PHP查找一列有序数组是否包含某值的方法
2020/02/07 PHP
一个JQuery写的点击上下滚动的小例子
2011/08/27 Javascript
jquery.validate的使用说明介绍
2013/11/12 Javascript
JS短路原理的应用示例 精简代码的途径
2013/12/13 Javascript
jQuery遍历对象、数组、集合实例
2014/11/08 Javascript
node.js中的events.emitter.removeListener方法使用说明
2014/12/10 Javascript
javascript实现图片左右滚动效果【可自动滚动,有左右按钮】
2016/09/19 Javascript
canvas绘制七巧板
2017/02/03 Javascript
webpack3.0升级4.0的方法步骤
2020/04/02 Javascript
vue - props 声明数组和对象操作
2020/07/30 Javascript
Map与WeakMap类型在JavaScript中的使用详解
2020/11/18 Javascript
python下读取公私钥做加解密实例详解
2017/03/29 Python
python中hashlib模块用法示例
2017/10/30 Python
Python3.遍历某文件夹提取特定文件名的实例
2018/04/26 Python
Python判断以什么结尾以什么开头的实例
2018/10/27 Python
python实现树的深度优先遍历与广度优先遍历详解
2019/10/26 Python
python 实现将list转成字符串,中间用空格隔开
2019/12/25 Python
Pytorch十九种损失函数的使用详解
2020/04/29 Python
PyCharm中配置PySide2的图文教程
2020/06/18 Python
tensorflow图像裁剪进行数据增强操作
2020/06/30 Python
使用python编写一个语音朗读闹钟功能的示例代码
2020/07/14 Python
为2021年的第一场雪锦上添花:用matplotlib绘制雪花和雪景
2021/01/05 Python
htnl5利用svg页面高斯模糊的方法
2018/07/20 HTML / CSS
Cole Haan官方网站:美国时尚潮流品牌
2017/12/06 全球购物
西铁城美国官方网站:Citizen Watch美国
2019/11/08 全球购物
进程的查看和调度分别使用什么命令
2013/12/14 面试题
2014年教师党员自我评议
2014/09/19 职场文书
《认识钟表》教学反思
2016/02/16 职场文书
浅谈Nginx 中的两种限流方式
2021/03/31 Servers
如何在CocosCreator里画个炫酷的雷达图
2021/04/16 Javascript