js闭包

在写这篇博客之前,其实我对闭包的理解停留在两个函数嵌套内函数可以访问外函数,会产生内存泄露这两个点上,确实也就这两个点,但是如果有人问你使用场景呢?为什么要用内函数去获取外函数的局部变量?有可能你会说返回给全局啊,这样全局可以用了,是的,但是,如果使这种需求,我直接把局部变量return 出去不就行啦,何必要再声明一个函数呢?

有人又会说内存泄露,你又猜对了,但是真的有人问你为什么会造成内存泄露,能举一个简单例子吗?你能写出来吗?能的话说明你不仅懂了闭包,其实你也已经懂了js回收机制。直到我看了阮一峰老师的文章确实简单易懂,在此谢谢并友情链接:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

容我像一个初学者一样慢慢道来:

// 最简单的闭包
    function outer() {
        var a = 1;
        function inner() {
            console.log(a)
        }
// return a }

这是一个闭包,但这不足以造成内存泄露,如果想要返回局部变量a的值,直接在outer里 return a,所以说这么普通的闭包真的是又麻烦又没有任何效果

// 返回一个函数
    function outer() {
        var a = 1;
      return function inner() {
            console.log(a)
        }
    }

这回高级一点了,返回了一个函数,那么返回一个函数难道就为了让外界获取局部a的值吗?显然有些花里胡哨,还是直接return a不好吗?花里胡哨复杂的代码,别人几行就能搞定,你说哪个牛?而用简单的方法就能实现的更牛。所以函数作为返回值绝不是仅仅用来让外界获取a的值的,而是外界更贪心,还想改变a的值。怎么做呢?请看:

function outer() {
        var a = 1;
      return function inner() {
            a = a + 1;
            console.log(a)
        }
    }
    
    // 调用返回的函数
    outer()();  // 2
    outer()();  // 2

这不是闹着玩吗?outer()就是inner函数,outer()()就是inner() 再来几个outer()()都是2,这是因为每次执行outer()都会把a重新赋值为1,我就要每次调用inner()就要把a自增

// 闭包式调用 --- 这是我自己添加的名词,不是官方的
    var fn = outer();
    fn() // 2
    fn() // 3

其实就是把返回的函数赋给了一个全局变量,简简单单的赋值,这就厉害了,如果用fn去掉用,就不会走var a = 1这条语句,也就是说不会在outer内重新赋值,而a不会走正常局部变量的该走的道路(局部变量执行就回收)。这就体现了第二个特点:局部变量难以回收。(造成内存泄漏) 这功能倒是适应以下情况:想让一个局部变量在原先处理的基础上操作,但是又需要初始化(这很重要),不想每次执行都把局部变量初始化了。有人一看:这简单,直接在全局里面写不就行了(码农);全局里面全局污染怎么办(相当于钱的余额能给别人查看和修改吗)(程序员), 防止全局污染使用函数,而在函数内要满足上述要求使用闭包,所以闭包也能防止变量污染。

斐波那契递归实现(闭包缓存版):

// 使用闭包缓存会减少很多的重复操作
    function fbnq(n){
        var cache = []
       return function handle() {
            var res;
            if(n == 1 || n == 2){
                return 1;
            }
            if (cache[n] == res){
                return cache[n]
            }else{
                res = fbnq(n-1) - fbnq(n-2)
                cache[n] = res;
                return res;
            }
        }
        return handle
    }


闭包讲完了,下面有兴趣的大佬们可以看看相关博客(其实是想听听大佬们的指点): js垃圾回收机制( 从这个角度也能了解把函数赋值给全局变量全局变量依赖内函数,那么内函数里面的变量就不能被清除【阮一峰的理解】 )

上一篇:Java中的内部类


下一篇:内部类