84669 Lernen von Personen
152542 Lernen von Personen
20005 Lernen von Personen
5487 Lernen von Personen
7821 Lernen von Personen
359900 Lernen von Personen
3350 Lernen von Personen
180660 Lernen von Personen
48569 Lernen von Personen
18603 Lernen von Personen
40936 Lernen von Personen
1549 Lernen von Personen
1183 Lernen von Personen
32909 Lernen von Personen
如图为什么结果会不一样呢
拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...
我是这样想的: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的值了)
f1()()的时候f1()会重新执行var n = 999;而r()时,n = 999只在 r = f1()时执行了一次。
因为每次函数调用都是不同的上下文,第二种方法f1只调用了一次,第二次调用r的时候,n还是之前的n,第一种就不同啦。
每次进入一个函数,都会将里面的语句全部执行一次,第一次调用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下!
我是这样想的:function f1(){
// f1();//这里还是指向的原对象
// f1()();//undefined
// nadd();//这里还是指向的原对象下面的方法--虽然是个闭包,但是因为是原对象的方法,且只调用一次,所以,正常输出1000;
var r=f1();//这里还是指向的原对象的链接(可以认为r把原对象拷贝了一份),即此对象!==f1()
// r();//这里是r(),即原对象的完成了拷贝,并且调用了f2方法,输出999,。如果是f1(),则不作输出(f1()下的方法都没被调用)
这里可以再这样子试试:
内容有点多,不知道题主能明白我的意思不?说到底,其实主要是var r=f1()这一句造成的影响,它将f1()发状态冻结了,从而引发后面nadd()的结果(准确的说是让nadd()能够修改到n的值了)
f1()()的时候f1()会重新执行var n = 999;而r()时,n = 999只在 r = f1()时执行了一次。
因为每次函数调用都是不同的上下文,第二种方法f1只调用了一次,第二次调用r的时候,n还是之前的n,第一种就不同啦。
每次进入一个函数,都会将里面的语句全部执行一次,第一次调用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下!