猿问

闭包可以让这些变量的值始终保持在内存中,那为什么这样输出后还是原来的值

function f1(){

    var n =9;

    nAdd=function(){

        n=n+1;

    }

    function f2(){

       console.log(n);

    }

    return f2;

}

 var result=f1();

 result(); //9

 nAdd();

 result();// 10


 var consult=f1();

 consult();//9

如图代码所示,正在学习闭包,阮老师提到闭包作用之一就是可以让这些变量的值始终保存在内存中,


1.那为什么consult()这里打印出来的不是10,而是9呢?n值不是被保存下来了吗?


2.还有就是“f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中” 这句话又是什么意思呢?f2为什么被赋给了一个全局变量?这个变量是谁?


白猪掌柜的
浏览 1562回答 2
2回答

宝慕林4294392

1.每次运行f1,函数体都会重新执行,所以在第二次运行f1后,nAdd函数体中的n已经变成了新的n,值为92.全局变量是result和consult。这句话的f2和f1指的是运行上下文,具体到这个问题可以理解为变量n和f2

回首忆惘然

闭包讲清楚不是很容易,我尽量讲得清楚些1.那为什么consult()这里打印出来的不是10,而是9呢?n值不是被保存下来了吗?这个问题可以简化下,实际就是下面这个问题:var result=f1(); // 内存里保存了一个 nvar consult=f1(); // 内存里也保存了一个 n问题是,但是这两个 n 是同一个么?如果是同一个,那就是题主的意思; 不是同一个,就是阮老师的意思;实际上不是同一个,js权威指南上是这么说的我的理解就是,这个 n 是函数调用的时候才添加到作用域链的,那么两次调用函数赋值给变量,当然声明了两次,添加了两次,而且在不同的作用域链中,如果是同一个 n 在同一个作用域,不就是重复声明了么?你把 var 换成 let 会报错的,为什么说在不同的作用域链中呢?当你声明了 consult 之后,consult的作用域链中全局对象里有 result,result的作用域链中全局对象里有 consult 嘛?明显没有啊,所以两个 n 在不同的作用域链中,当然不是同一个;或者再粗浅理解下,你调用一个函数两次赋值给不同变量,难道函数内的变量都是为两个变量共享,用的是同一个嘛?当然不是啊,,,2.还有就是“f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中” f2为什么被赋给了一个全局变量?这个变量是谁?var result=f1(); // f1() 函数执行到 return f2,就把 f2 赋值给了 result,result 是全局变量var consult=f1(); // f1() 函数执行到 return f2,就把 f2 赋值给了 consult,consult 是全局变量2.还有就是“f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中” 这句话又是什么意思呢?var result=f1();//result=f2 不完全等价,但是可以用来参考因为把 f2 赋值给 result,实际上就是在 result 上保存了对 f2的引用,而 f2 里又保存了对 n 的引用,而 f2 和 n 都存在于 f1 的局部环境里,所以导致了 n,f2,f1 都不会被垃圾回收,也就是说 f2,f1,n 都保存在内存中;(因为 js 的垃圾回收机制存在引用计数的规则,当这个值的引用次数变成 0 时,这个值才会被垃圾回收,释放内存,引用次数不为 0 ,就继续保存在内存中,不会被垃圾回收)(实际上我觉得 f1 已经不在内存中了,不过这个不影响闭包的理解)
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答