这个js函数的输出的结果不一样的原因是什么呢?

发布于 2022-09-04 05:06:48 字数 142 浏览 16 评论 0

如图为什么结果会不一样呢
图片描述

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

Hello爱情风 2022-09-11 05:06:48

每次进入一个函数,都会将里面的语句全部执行一次,第一次调用f1()()会定义一个函数级别变量n,并且将隐性全局变量的值设为一个函数,注意这个函数因为是在f1中定义的,所以它可以引用它创建时的所有变量,这也就是闭包的由来,对于没有闭包的情况,函数内的函数级别变量(函数内用var声明的)都会在函数结束后销毁,但是一旦存在闭包,也就是逃逸出这个函数级作用域的函数(不管你是通过返回函数,或者设置为全局变量),这个逃逸的函数,都可以访问它创建时的所有可见变量,阻止浏览器回收这些变量。
每次调用f1是都会定义一个函数体完全一样但是却是不同函数的函数对象,所以第一次调用f1()后,已经形成了闭包:返回的f2盒全局的nadd,调用f1()()的结果就是调用了返回的f2,这时第一次调用f1时创建的n1(这个1代表它是第一次创建的,仅仅为了表述清楚,实际上它是n),就是999,然后调用nadd()n1被加一,所以输出了1000,但是你再次调用f1(),这时有趣的事情发生了,f1的函数体要再执行一次,看似好像nadd没有改变,但是其实它已经指向了一个新的函数,尽管这个函数的函数体和它之前的函数体是完全一样的,但是它们是不同的对象,最大的不同就在于可以访问的变量不同,第二次的nadd,可以访问的已经不再是n1,而是第二次调用f1()创建的n2了,这个n2的值为999,至于n1呢?它因为已经没有函数可以访问,被回收啦!因为返回的f2并未被存为变量而且第一次f1中定义的nadd也已经不在了。
后面的为什么是那个结果题主可以自己想一下,闭包是js中的一个双刃剑,威力无穷也很蛋疼,但是只要好好思考是很好理解的,一旦理解,合理的使用闭包会带来很多好处,但是也有很多坑需要注意,具体的题主可以google下!

戈亓 2022-09-11 05:06:48

因为每次函数调用都是不同的上下文,第二种方法f1只调用了一次,第二次调用r的时候,n还是之前的n,第一种就不同啦。

爱你不解释 2022-09-11 05:06:48

f1()()的时候f1()会重新执行var n = 999;
而r()时,n = 999只在 r = f1()时执行了一次。

剑心龙吟 2022-09-11 05:06:48

我是这样想的:function f1(){

            var n=999;
            nadd=function (){
                n+=1;
                console.log("n的值为"+n);
            }
            function f2(){
                console.log(n);
            }
            return f2;
        }

// f1();//这里还是指向的原对象
// f1()();//undefined
// nadd();//这里还是指向的原对象下面的方法--虽然是个闭包,但是因为是原对象的方法,且只调用一次,所以,正常输出1000;

        var r=f1();//这里还是指向的原对象的链接(可以认为r把原对象拷贝了一份),即此对象!==f1()

// r();//这里是r(),即原对象的完成了拷贝,并且调用了f2方法,输出999,。如果是f1(),则不作输出(f1()下的方法都没被调用)

        nadd();//无论上一行是f1()还是r(),作为函数内的闭包,被调用一次(注意,当前它其实是r的路径指向的原函数下了)
        r();//如果前面为f1(),即意味着这里是var r=f1()拷贝后的第一次调用f2()输出999,如果前面为r(),即意味着这里是第二次调用,同样输出f2(),但是不同的是,前面的nadd()已经影响到了r中的n,即f1()中的var n=999;已经被替换为n+=1;并且已经执行一次了,所以,当前的n为1000(闭包保存了n)。

这里可以再这样子试试:

        var r=f1();
        f1();//不作输出,r()没调用
        
        nadd();//n被保护,且加一,为1000;
        nadd();//n被保护,且加一,为1001;
        r();//999,因为这里才是r拷贝的路径后执行的第一次,在它复制的那一刻,n=999.所以f2()输出999

内容有点多,不知道题主能明白我的意思不?说到底,其实主要是var r=f1()这一句造成的影响,它将f1()发状态冻结了,从而引发后面nadd()的结果(准确的说是让nadd()能够修改到n的值了)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文