JS闭包理解

首先,JavaScript的变量只有两种:即为全局变量和局部变量;

因为JavaScript语言的链式作用域结构,子对象可以一级一级的向上寻找父对象的变量,所以,父对象的所有变量对子对象都是可见的,但是因为是单向作用域链,所以反之不成立

所以到现在,函数内部可以直接读取全局变量,如:

  var a = 1
    function demo1() {
        alert(a)
    }
    demo1()  // 弹出数值为1的提示框
但是,如果想要在函数外部读取函数内的局部变量却无法做到,如
 function demo1() {
        var a = 1
    }
    alert(a)  // 错误,提示a没有定义,
注意,如果在函数中不使用var来定义变量,如直接a=1,则a会成为全局变量,如
 function demo1() {
        a = 1
    }
    demo1()  //这里要先执行一下函数,否则a不会被声明
    alert(a)  // 弹出数值为1的提示框
那么,想要实现在函数外部读取函数内的局部变量的操作,就要用到闭包,如
 function demo1() {
        var a = 1   // 局部变量
        function demo2() {  //如何实现闭包:即在函数的内部再定义一个函数
            a += 1  //因为作用域链,所以此处可以访问到a
            console.log('此a为:' + a)
        }
        return demo2  //这里返回的函数不用加括号,即返回函数名不加括号,调用函数的时候才加括号
    }
 
    console.log(typeof(demo1()))      //输出function,如果上面return 的是demo2(),那么返回undefined,并且报错
    var result = demo1()  //先执行函数,给变量赋值
    console.log(typeof(result))          //输出function,如果上面return 的是demo2(),那么返回undefined,并且报错
    result() // 执行函数,实现对局部变量a的访问
    result()
    result()
    result()
    result()
闭包的用途:
1.读取函数内部的变量
2.让函数内部的变量的值始终保存在内存中,如
 function demo1() {
        var n = 1
        add = function() {    // 这里是一个全局变量
            n += 1
        }
        // return n
        function demo2() {
            alert(n)
        }
        return demo2
    }
    var result = demo1()
    result() // 显示1
    add()
    result() //显示2
    // console.log(demo1())
    // add()
    // console.log(demo1())
在这段代码中,result即为闭包demo2函数,第一次的值为1,第二次的值为2,这证明了函数demo1中的局部变量n一直保存在内存中,并没有在demo1被调用后被回收
这里demo1是demo2的父函数,而demo2被赋给了一个全局变量result,这导致demo2始终在内存中,而demo2的存在依赖于demo1,所以demo1也是种存在于内存中,不会在调用结束后被回收机制回收
这里的add函数其实是一个全局变量,如果把闭包函数demo2注释掉,运行下面注释的语句,就会发现两次输出的值都是1,这是因为局部变量在第一次被调用结束后被回收了,即使执行了全局函数add,也不会对局部变量n产生影响,这恰恰验证了闭包使局部变量的值始终存在于内存中,不会因调用结束而被回收
 
使用闭包的注意点:
1.由于闭包会使得函数中的变量都被保存在内存中,会占用内存,所以不能滥用闭包,否则会造成网页的性能问题,可能导致内存泄漏。解决方法是在退出函数之前,将不使用的局部变量全部删除(delete或者设置该变量为null)
2.闭包会在函数外部,改变函数内部变量的值,所以一定要小心使用,不能随便改变父函数内部变量的值
 
 
 
 
 
 
 
 
 
可以执行一下下面两个demo,挺有意思的

var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      return function(){
        return this.name;
      };

    }

  };

  alert(object.getNameFunc()());    // 这里把立即执行的括号去掉输出一下就很清楚了,我的理解是这个demo里没有闭包,被返回的函数没有属于的对象,所以this指向全局。

 

var name = "The Window";

  var object = {
    name : "My Object",

    getNameFunc : function(){
      var that = this;
      return function(){
        return that.name;
      };

    }

  };

  alert(object.getNameFunc()());   //而这里因为有一个that,所以它需要依赖getNameFunc这个函数,就形成了一个闭包,局部变量会一直在内存中,that点的就是局部变量的值

  
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
    
posted @ 2020-03-30 15:50  ajjoker  阅读(100)  评论(0)    收藏  举报