JS闭包 只要一块芒果千层的时间,就能吃透的闭包

学习js的时候,或多或少会了解到闭包,因为有点奇怪,所以晦涩难懂。下面是闭包创建的部分概念。

 闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。闭包会发生内存泄漏,每次外部函数执行的时候,外部函数的引用地址不同,都会重新创建一个新的地址

上文来源文章-https://blog.csdn.net/weixin_43586120/article/details/89456183,很不错的文章,推荐大家去看一下。下面的一些代码例子也是参考这篇文章来的,如果上文作者觉得冒犯,我会删除此文章

       然后我们细品这段话(默念十遍,红色字请放慢念),你就会发现当外部引用的地址不同才会创建一个新地址,也就是说当引用地址没有变化的时候,闭包里面的变量就不会刷新,当引用了新的地址的时候,闭包里面的变量就会刷新。基于这段话我们来"康康"几个例子我们就懂了。

例子1、

function fun1(){
    var num = 0;
    function fun2(){
      num ++;
      console.log(num)
    }
    return fun2
}
var a = fun1();
var b = fun1();
a();
b();
a();
b(); 
//输出为 1 1 2 2

看蛤,用上面说的那句话的理解就是,a是不是一个新地址?是。b是不是一个新的地址?是。所以说a和b是互不影响。所以在b()前面调用多少个a(),也不会影响b的函数本身自己的变量。哪,我按下面来调用呢?

fun1()()
fun1()()
//输出为 1 1 

一样的,这两个引用的地址不一样,所以互不影响。 (补充,可能有些读者看不懂为什么是两个括号,那是因为第一个括号就是调用了fun1的方法,然后fun1返回fun2方法,所以第二括号的意思就是调用fun1中的fun2方法)根据这个补充我们引入下一个例子。

例子2、

var fun1 = function(x) { 
    var sum = 1; 
    var fun2 = function(x) { 
        sum = sum + x; 
        return fun2;    
    } 
    fun2.toString = function() { 
        return sum; 
    }
    return fun2; 
} 
console.log(fun1(1)(2)(3));  
//输出为 6 

可能有些读者上来就懵了。这是啥?不过我们是受过专业训练的人,是不会害怕的,除非真的很恐怖。不过这个并不难理解,三个括号的解读可以参考一段的补充。细看这些代码,第一个括号,fun1(1)这个方法执行后就会生成有一个新地址,执行sum=1,并返回了fun2函数,第二个括号就是调用这个返回来的fun2函数,fun2函数可以接收一个参数,并和sum相加。因为内存没有变化,所以此时sum为第一个括号执行出来的1,并不是传入的1所以你执行下面代码:

console.log(fun1()(2)(3));  
//输出为 6 
console.log(fun1(800000)(2)(3));  
//输出为 6 

也是一样的。可能还有同学疑惑:“哪,哪参数x呢?”其实啊,这个x,因为在fun1里面并没有调用fun2,只是调用了fun2的toString方法,所以这两个x没什么影响,除非fun1里面调用了fun2。接回上文执行fun2(2)后,sum的值就变成1 + 2也就是3了,同类,第三个括号就变为3+3了,所以结果为6,当然,你可以一直套娃下去。回顾整个过程,创建闭包的地址没有发生变化,所以sum的值并没有刷新。基于这里,我们来个改版,在fun2里面调用fun1,看下面例子3.

例子3、

function fun1(num1, num2) {
      console.log(num2);
      return {
           fun2:function(num3) {
                 return fun1(num3, num1);
           }
      };
}
var a = fun1(0);  //undefined
a.fun2(1);        //0  
a.fun2(2);        //0  
a.fun2(3);        //0  
var b = fun1(0).fun2(1).fun2(2).fun2(3);
//undefined  0  1  2

可能你一看又懵了,怎么又是套娃。其实奥利giao就完事了(别的代码是fun2和fun1同名,那才恶心,所以我这里特意分开两个名字,方便理解。其实同名也是一样的)。

看这里,a是一个新的地址,b也是一个新地址,这两个互不影响。无论a怎么操作,是无法影响b的。确定这个后,我们又回来看这些代码,按照上段的解读来看,看完上文的大家都已经懂得七七八八了。为什么第一个是undefined,因为没传参数啊,为什么a.fun2(1)....等等都是0啊,你看看fun2的执行就懂了,num1=0,已经在var a = fun1(0);已经确定了,a无论后面怎么调用fun2,是不会影响当初fun1传来的num1 = 1的。而且a.fun2(x)然后看b的那串套娃。一样的,带入一下就很好理解; 

最后,综上所述,看闭包的变量是否变化,我个人觉得就是是靠引用闭包的地址是否发生改变。如有错误请指出,非常感谢。

发布了3 篇原创文章 · 获赞 5 · 访问量 1072

猜你喜欢

转载自blog.csdn.net/weixin_39394140/article/details/105551971