摘要:我的理解就是還處于被引用狀態。內存機制的內存空間分為棧堆其中棧存放變量,堆存放復雜對象。對堆內數據進行復制修改時理解閉包有了前面的鋪墊,我們再來看看閉包是怎么回事。這種反常的現象我們就叫它,中文名閉包。這就是閉包形成的原因了。
知識小儲備
ECMAScript 的數據有兩種類型:基本類型值和引用類型值,基本類型指的是簡單的數據段,引用類型指的是可能由多個值構成的對象。垃圾回收Undefined、Null、Boolean、Number 和 String 是值類型,其他都是引用類型。
我們創建的原始類型、對象、函數等等,都會占用內存。為了防止溢出,我們就需要對不用的數據進行刪除。這就是垃圾回收。
可觸及(Reachability)JavaScript 內存管理的關鍵概念是可觸及(Reachability)。
我的理解就是還處于被引用狀態。
將全局(無論是window還是global)比作樹根,我們創建的原始類型、對象、函數等等比作一個個枝杈。如果可以從window不斷層的知道某個變量,那這個變量就是可觸及的,不可回收的。
舉個例子:
// user has a reference to the object let user = { name: "John" };
箭頭代表的是對象引用。全局變量 "user" 引用了對象{name: "John"}(簡稱此對象為 John)。John 的 "name" 屬性儲存的是一個原始值,所以無其他引用。
如果覆蓋 user,對 John 的引用就丟失了:
user = null;
現在 John 變得不可觸及,垃圾回收機制會將其刪除并釋放內存。
內存機制js的內存空間分為棧 (stack)、堆 (heap);其中棧存放變量,堆存放復雜對象。
借用一張圖直觀感受一下
只能存放基本數據類型的數據和對象類型的引用地址也叫哈希碼。里面的數據后進先出。
對棧內數據進行復制修改時:
是用來存儲 “數組類型” 和“對象類”的數據。特點是存儲空間大。
對堆內數據進行復制修改時:
有了前面的鋪墊,我們再來看看閉包是怎么回事。還是舉個例子:
//決策層開會決定生產新一代phone手機,就弄了個叫PhoneFactory的企劃案 let Proposal = function(){ //新一代手機信息被封裝在企劃案中 let version = "XX", money = 10000 return function (){ //生產新的手機 return { version: version, money: money } } } //執行者根據策劃案建成了一個工廠, 工廠方法每執行一次就產出一個手機 let Factory = new Proposal(); let phone1 = Factory(); console.log(phone1.version)
對于手機的version, money而言, 它是策劃書Proposal的內部變量,而Proposal的同級phone1應該是訪問不到。但實際上我們還是拿到了手機的版本和價格數據。這種反常的現象我們就叫它Closure,中文名閉包。
原因我們不管它為什么叫這個名字,先看看具體是什么原因產生的。
根據上面說的垃圾回收機制。函數Proposal在執行過之后(第16行)就沒有引用。那么Proposal久應該被回收。里面的所有內部變量也應該被回收了。
但實際上 Proposal返回了一個新的函數Factory。而這個Factory是要能夠訪問到它生成時的同級以及父祖輩變量。而Proposal內部變量version, money就有了新的引用。因而阻止了被回收。就像Factory生成了一個新的泡泡把它能訪問到的作用域包裹了起來。這就是閉包形成的原因了。
基于上面的js內存機制的知識,我們可以畫出下面這張圖:
圖簡陋了點。。。。
但也可以看出,對于變量version,money而言。雖然他們本身在proposal的黃色作用域中。但也在fatory生成的時候也被包含在了fatory打的可訪問的作用域氣泡內。不僅他們,甚至更外層的也都被包含在內。
在proposal這個泡泡破碎之后,只有當打的紅色泡泡也破了,這些變量才會真的被回收。這也是為什么閉包用多了會影響性能的原因。
前端基礎進階:詳細圖解 JavaScript 內存空間
垃圾回收
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/96310.html
摘要:如何在初學就理解閉包你需要接著讀下去。這樣定義閉包是函數和聲明該函數的詞法環境的組合。小結閉包在中隨處可見。閉包是中的精華部分,理解它需要具備一定的作用域執行棧的知識。 這是本系列的第 4 篇文章。 作為 JS 初學者,第一次接觸閉包的概念是因為寫出了類似下面的代碼: for (var i = 0; i < helpText.length; i++) { var item = he...
摘要:當初看這個解釋有點懵逼,理解成閉包就是函數中的函數了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學習語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數作為值返回的情況,被返回的函數引用了生成它的母函數中的變量。 本人開始接觸編程是從js開始的,當時網上很多人說閉包是難點,各種地方對閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發現不光是js,php、...
摘要:當初看這個解釋有點懵逼,理解成閉包就是函數中的函數了。里的閉包最近不滿足于只干前端的活,開始用起了。里的閉包最近在學習語言,讓我們來看一下語言里的閉包。在中,閉包特指將函數作為值返回的情況,被返回的函數引用了生成它的母函數中的變量。 本人開始接觸編程是從js開始的,當時網上很多人說閉包是難點,各種地方對閉包的解釋也是千奇百怪。如今開始接觸js以外的各種編程語言,發現不光是js,php、...
摘要:閉包在我理解是一種比較抽象的東西。所以我寫了一篇博文來方便自己理解閉包。那么現在我們可以解釋一下閉包的第一個定義在計算機科學中,閉包是引用了自由變量的函數。循環中創建閉包在我們使用的關鍵字之前,閉包的一個常見問題就出現在循環中創建閉包。 零. 前言 從我開始接觸前端時就聽說過閉包,但是一直不理解閉包究竟是什么。上網看了各種博客,大家對閉包的說法不一。閉包在我理解是一種比較抽象的東西。所...
摘要:但是閉包也不是什么復雜到不可理解的東西,簡而言之,閉包就是閉包就是函數的局部變量集合,只是這些局部變量在函數返回后會繼續存在??上У氖?,并沒有提供相關的成員和方法來訪問閉包中的局部變量。 (收藏自 技術狂) 前言:還是一篇入門文章。Javascript中有幾個非常重要的語言特性——對象、原型繼承、閉包。其中閉包 對于那些使用傳統靜態語言C/C++的程序員來說是一個新的語言特性。本文將...
閱讀 3783·2021-08-30 09:47
閱讀 3723·2019-08-30 15:56
閱讀 685·2019-08-30 14:18
閱讀 705·2019-08-29 16:17
閱讀 2072·2019-08-29 11:07
閱讀 652·2019-08-26 13:53
閱讀 3457·2019-08-26 10:26
閱讀 2504·2019-08-23 18:30