武汉web培训
达内武汉中心

15827352908

热门课程

JavaScript匿名函数和闭包

  • 时间:2016-07-20 10:47
  • 发布:milan
  • 来源:web前端网

匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数。
一.匿名函数
eg.
   //把匿名函数赋值给变量
   var box = function () { //将匿名函数赋给变量
         return 'Lee';
   };

   //函数里的匿名函数
   function box () {
      return function () { //函数里的匿名函数,产生闭包
          return 'Lee';
      }
  }
   alert(box()()); //调用匿名函数

二.闭包
闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,
就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变。

eg.
   //通过闭包可以返回局部变量
   function box() {
      var user = 'Lee';
      return function () { //通过匿名函数返回box()局部变量
           return user;
      };
  }
  alert(box()()); //通过box()()来直接调用匿名函数返回值
  闭包有一个优点,也是它的缺点:就是可以把局部变量驻留在内存中,可以避免使用全局变量。
  由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降  作用域链的机制导致一个问题,在循环中里的匿名函数取得的任何变量都是最后一个值。
  eg.
    //循环里包含匿名函数                                                                                function box() {
         var arr = [];
        for (var i = 0; i < 5; i++) {
              arr = function () {         
                  return i;
              };
        }
        return arr;
    }
   var b = box(); //得到函数数组
   for (var i = 0; i < b.length; i++) {
          alert(b()); //b调用的是匿名函数,匿名函数并没有自我执行
                           //等到调用的时候,box()已执行完毕,i 早已变成5
   }
   通过匿名函数自我执行,立即把结果赋值给a。每一个i,是调用方通过按值传递的,
   所以最终返回的都是指定的递增的i。而不是box()函数里的i。
  eg.
    //循环里包含匿名函,自我执行匿名函数
      function box() {
          var arr = [];
          for (var i = 0; i < 5; i++) {
               arr = (function (num) { //自我执行
                   return num;
              })(i); //并且传参
          }
         return arr;
     }
     var b = box();
     for (var i = 0; i < b.length; i++) {
           alert(b); //这里返回的是数组,直接打印即可
     }

   在闭包中使用this 对象也可能会导致一些问题,this 对象是在运行时基于函数的执行环境绑定的,
   如果this 在全局范围就是window,如果在对象内部就指向这个对象。而闭包却在运行时指向window 的,
   因为闭包并不属于这个对象的属性或方法。
   可以用call()强制闭包中this指向某个对象,如下getUserFunction()为对象obj的内部匿名函数
    eg.
       var obj = {
           user : 'The Object',
           getUserFunction : function () {
                     return function () { //闭包不属于obj,里面的this 指向window
                              return this.user;
                      };
           }
       };
    alert(obj.getUserFunction().call(obj)); //The Object,可以强制指向某个对象
    //也可以从上一个作用域中得到对象
     getUserFunction : function () {
         var that = this; //从对象的方法里得对象
         return function () {
              return that.user;
         };
     }

   IE内存泄漏问题:
   闭包在IE中会导致内存泄漏的问题,也就是无法销毁驻留在内存中的元素。
   function box() {
       var oDiv = document.getElementById('oDiv'); //oDiv 用完之后一直驻留在内存
       oDiv.onclick = function () {
           alert(oDiv.innerHTML); //这里用oDiv 导致内存泄漏,需要等到浏览器关闭才得以释放
       };
      oDiv = null; //在最后应该将oDiv 解除引用来避免内存泄漏。
   }
   box();

  模仿块级作用域  JavaScript 没有块级作用域的概念,if () {} for () {}等没有作用域。
  eg.
    function box(count) {
      for (var i=0; i<count; i++) {}
      alert(i); //i 不会因为离开了for 块就失效
   }
  box(2);//2

  JavaScript 不会提醒你是否多次声明了同一个变量它只会对后续的声明视而不见(如果初始化了,当然还会执行的)。
  使用模仿块级作用域可避免这个问题。


  //使用块级作用域(私有作用域
   function box(count) {
       (function () {
             //这里是块级作用域
             for (var i = 0; i<count; i++) {}
       })();
      alert(i); //报错,无法访问
   }
   box(2);

   使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁。
   这种技术经常在全局作用域中被用在函数外部,从而限制向全局作用域中添加过多的变量和函数。
 
   在全局作用域中使用块级作用域可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。
   只要函数执行完毕,就可以立即销毁其作用域链了。

   私有变量
   JavaScript 没有私有属性的概念;所有的对象属性都是公有的。
  但是有私有变量的概念:任何在函数中定义的变量,即是私有变量,因为不能在函数的外部访问这些变量。

马上预约七天免费试听课

姓名:

电话:

上一篇:现代开发高手的终极秘诀
下一篇:9大理由告诉你为什么应该学习HTML跟CSS

web前端学习容易犯的错误

web1702“诱人”活动

抽象类和抽象方法

jquery的ajax和getJson跨域获取json数据

选择城市和中心
贵州省

广西省

海南省

有位老师想和您聊一聊