2 回答

TA貢獻2021條經驗 獲得超8個贊
1.每次運行f1
,函數體都會重新執行,所以在第二次運行f1
后,nAdd
函數體中的n
已經變成了新的n
,值為9
2.全局變量是result
和consult
。這句話的f2
和f1
指的是運行上下文,具體到這個問題可以理解為變量n
和f2

TA貢獻1847條經驗 獲得超11個贊
閉包講清楚不是很容易,我盡量講得清楚些
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 已經不在內存中了,不過這個不影響閉包的理解)
添加回答
舉報