摘要:閉包是怎么通過作用域鏈霸占更多內存的本文是作者學習高級程序設計第一小節的一點個人理解,詳細教程請參考原教材。函數執行過程創建了一個函數的活動對象,作用域鏈的最前端指向這個對象。函數執行完畢返回值后執行環境作用域鏈和活動對象一并銷毀。
JavaScript 閉包是怎么通過作用域鏈霸占更多內存的?
本文是作者學習《JavaScript 高級程序設計》7.2第一小節的一點個人理解,詳細教程請參考原教材。
在弄清楚這個問題之前,我們有必要搞清楚下面這幾個問題:
首先,什么是閉包?怎么創建閉包?定義:閉包 是指 有權訪問另一個函數作用域中變量的函數。
一個一般的函數執行的時候都發生了什么?在一個函數內部創建另一個函數,是創建閉包最常見的方式。
創建一個執行環境,里面有這個函數的變量對象,保存了函數可訪問的所有數據。
創建了作用域鏈,用來保證可訪問變量的有序訪問。
函數執行過程創建了一個函數的活動對象,作用域鏈的最前端指向這個對象。
函數讀取寫入值,在作用域鏈里面查找。
函數執行完畢返回值后:執行環境、作用域鏈和活動對象一并銷毀。
理解了這些之后,考察下原書的代碼:
function createCompare(property){ return function(obj1,obj2){ var value1=obj1.property; var value2=obj2.property; if (value2 < value1){ return 1; } else if (value2 >value1){ return 1; } else { return 0; } }; } var compareNames = createCompare("name"); var result = compareNames({name : "mars1"},{name : "mars2"});
其中,createCompare 函數返回了一個匿名函數,這個匿名函數就是一個閉包。它引用了createCompare函數的參數變量property。
創建compareNames 變量的時候,就創建了createCompare函數的活動變量:其中property = name etc. 同時返回了匿名函數給compareNames變量,它也有自己的執行環境與作用域鏈,作用域鏈引用了創建的compareNames活動對象。
result 定義過程,創建了compareNames的活動對象,其中obj1 = {name : "mars1"} etc.
這樣,為result 賦值的compareNames函數執行環境的作用域鏈如下:
那么問題來了,這個閉包是怎么導致占用更多內存的?compareNames活動對象 → createCompare活動對象 → 全局對象。
函數執行完畢,compareNames 變量并未消失,不會被垃圾回收,而它指向的閉包(匿名函數)的作用域鏈引用著createCompare 函數的活動變量。所以createCompare函數雖然執行完畢返回了匿名函數,但是它的活動對象并不會和執行環境、作用域鏈一樣被銷毀,因為還有compareNames的作用域鏈在引用。這樣就相當于閉包攜帶了包含它的函數活動對象。
因此要釋放compareNames攜帶的作用域,必須手動解除引用:
var compareNames = null;
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/81593.html
摘要:但是,必須強調,閉包是一個運行期概念。通過原型鏈可以實現繼承,而與閉包相關的就是作用域鏈。常理來說,一個函數執行完畢,其執行環境的作用域鏈會被銷毀。所以此時,的作用域鏈雖然銷毀了,但是其活動對象仍在內存中。 學習Javascript閉包(Closure)javascript的閉包JavaScript 閉包深入理解(closure)理解 Javascript 的閉包JavaScript ...
摘要:語句中的塊語句對來說,將會指定對象添加到作用域鏈中。在嚴格模式下,初始化未經聲明的變量會導致錯誤。查詢標識符搜索過程從作用域鏈的前端開始,向上逐級查詢與給定名字匹配的標識符。 本文記錄了我在學習前端上的筆記,方便以后的復習和鞏固。 4.1基本類型和引用類型的值 ECMAScript變量可能包含兩種不同數據類型的值:基本類型值和引用類型值。基本類型指的是簡單的數據段,而引用類型值指那些可...
摘要:之前一篇文章我們詳細說明了變量對象,而這里,我們將詳細說明作用域鏈。而的作用域鏈,則同時包含了這三個變量對象,所以的執行上下文可如下表示。下圖展示了閉包的作用域鏈。其中為當前的函數調用棧,為當前正在被執行的函數的作用域鏈,為當前的局部變量。 showImg(https://segmentfault.com/img/remote/1460000008329355);初學JavaScrip...
摘要:定義函數表達式的方式有兩種函數聲明。不過,這并不是匿名函數唯一的用途。可以使用命名函數表達式來達成相同的結果閉包匿名函數和閉包是兩個概念,容易混淆。匿名函數的執行環境具有全局性,因此其對象通常指向通過改變函數的執行環境的情況除外。 定義函數表達式的方式有兩種: 函數聲明。它的重要特征就是 函數聲明提升(function declaration hoisting) 即在執行代碼之前會...
摘要:閉包面試題解由于作用域鏈機制的影響,閉包只能取得內部函數的最后一個值,這引起的一個副作用就是如果內部函數在一個循環中,那么變量的值始終為最后一個值。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第8天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了...
閱讀 670·2023-04-25 18:59
閱讀 1210·2021-09-22 16:00
閱讀 1888·2021-09-22 15:42
閱讀 3593·2021-09-22 15:27
閱讀 1245·2019-08-30 15:54
閱讀 1104·2019-08-30 11:16
閱讀 2444·2019-08-29 16:24
閱讀 820·2019-08-29 12:14