国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

前端基礎進階(一):內存空間詳細圖解

_Suqin / 2739人閱讀

摘要:一棧數據結構與不同,中并沒有嚴格意義上區分棧內存與堆內存。引用數據類型的值是保存在堆內存中的對象。不允許直接訪問堆內存中的位置,因此我們不能直接操作對象的堆內存空間。為了更好的搞懂變量對象與堆內存,我們可以結合以下例子與圖解進行理解。

var a = 20;
var b = "abc";
var c = true;
var d = { m: 20 }

因為JavaScript具有自動垃圾回收機制,所以對于前端開發來說,內存空間并不是一個經常被提及的概念,很容易被大家忽視。特別是很多不是計算機專業的朋友在進入到前端之后,會對內存空間的認知比較模糊,甚至有些人干脆就是一無所知。

當然也包括我自己。在很長一段時間里認為內存空間的概念在JS的學習中并不是那么重要。可是后我當我回過頭來重新整理JS基礎時,發現由于對它們的模糊認知,導致了很多東西我都理解得并不明白。比如最基本的引用數據類型和引用傳遞到底是怎么回事兒?比如淺復制與深復制有什么不同?還有閉包,原型等等。

因此后來我才漸漸明白,想要對JS的理解更加深刻,就必須對內存空間有一個清晰的認知。

在學習內存空間之前,我們需要對三種數據結構有一個直觀的認知。他們分別是堆(heap),棧(stack)與隊列(queue)

一、棧數據結構

與C/C++不同,JavaScript中并沒有嚴格意義上區分棧內存與堆內存。因此我們可以簡單粗暴的理解為JavaScript的所有數據都保存在堆內存中。但是在某些場景,我們仍然需要基于堆棧數據結構的思維來實現一些功能,比如JavaScript的執行上下文(關于執行上下文我會在下一篇文章中總結)。執行上下文的執行順序借用了棧數據結構的存取方式。(也就是后面我們會經常提到的函數調用棧)。因此理解棧數據結構的原理與特點十分重要。

要簡單理解棧的存取方式,我們可以通過類比乒乓球盒子來分析。如下圖左側。

這種乒乓球的存放方式與棧中存取數據的方式如出一轍。處于盒子中最頂層的乒乓球5,它一定是最后被放進去,但可以最先被使用。而我們想要使用底層的乒乓球1,就必須將上面的4個乒乓球取出來,讓乒乓球1處于盒子頂層。這就是棧空間先進后出,后進先出的特點。圖中已經詳細的表明了棧空間的存儲原理。

二、堆數據結構

堆數據結構是一種樹狀結構。它的存取數據的方式,則與書架與書非常相似。

書雖然也整齊的存放在書架上,但是我們只要知道書的名字,我們就可以很方便的取出我們想要的書,而不用像從乒乓球盒子里取乒乓一樣,非得將上面的所有乒乓球拿出來才能取到中間的某一個乒乓球。好比在JSON格式的數據中,我們存儲的key-value是可以無序的,因為順序的不同并不影響我們的使用,我們只需要關心書的名字。

三、隊列

在JavaScript中,理解隊列數據結構的目的主要是為了清晰的明白事件循環(Event Loop)的機制到底是怎么回事。在后續的章節中我會詳細分析事件循環機制。

隊列是一種先進先出(FIFO)的數據結構。正如排隊過安檢一樣,排在隊伍前面的人一定是最先過檢的人。用以下的圖示可以清楚的理解隊列的原理。

四、變量對象與基礎數據類型

JavaScript的執行上下文生成之后,會創建一個叫做變量對象的特殊對象(具體會在下一篇文章與執行上下文一起總結),JavaScript的基礎數據類型往往都會保存在變量對象中。

嚴格意義上來說,變量對象也是存放于堆內存中,但是由于變量對象的特殊職能,我們在理解時仍然需要將其于堆內存區分開來。

基礎數據類型都是一些簡單的數據段,JavaScript中有5中基礎數據類型,分別是Undefined、Null、Boolean、Number、String。基礎數據類型都是按值訪問,因為我們可以直接操作保存在變量中的實際的值。

ES6中新加了一種基礎數據類型Symbol,可以先不用考慮他
五、引用數據類型與堆內存

與其他語言不同,JS的引用數據類型,比如數組Array,它們值的大小是不固定的。引用數據類型的值是保存在堆內存中的對象。JavaScript不允許直接訪問堆內存中的位置,因此我們不能直接操作對象的堆內存空間。在操作對象時,實際上是在操作對象的引用而不是實際的對象。因此,引用類型的值都是按引用訪問的。這里的引用,我們可以理解為保存在變量對象中的一個地址,該地址與堆內存的實際值相關聯。

為了更好的搞懂變量對象與堆內存,我們可以結合以下例子與圖解進行理解。

var a1 = 0;   // 變量對象
var a2 = "this is string"; // 變量對象
var a3 = null; // 變量對象

var b = { m: 20 }; // 變量b存在于變量對象中,{m: 20} 作為對象存在于堆內存中
var c = [1, 2, 3]; // 變量c存在于變量對象中,[1, 2, 3] 作為對象存在于堆內存中

因此當我們要訪問堆內存中的引用數據類型時,實際上我們首先是從變量對象中獲取了該對象的地址引用(或者地址指針),然后再從堆內存中取得我們需要的數據。

理解了JS的內存空間,我們就可以借助內存空間的特性來驗證一下引用類型的一些特點了。

在前端面試中我們常常會遇到這樣一個類似的題目

// demo01.js
var a = 20;
var b = a;
b = 30;

// 這時a的值是多少?
// demo02.js
var m = { a: 10, b: 20 }
var n = m;
n.a = 15;

// 這時m.a的值是多少

在變量對象中的數據發生復制行為時,系統會自動為新的變量分配一個新值。var b = a執行之后,a與b雖然值都等于20,但是他們其實已經是相互獨立互不影響的值了。具體如圖。所以我們修改了b的值以后,a的值并不會發生變化。

在demo02中,我們通過var n = m執行一次復制引用類型的操作。引用類型的復制同樣也會為新的變量自動分配一個新的值保存在變量對象中,但不同的是,這個新的值,僅僅只是引用類型的一個地址指針。當地址指針相同時,盡管他們相互獨立,但是在變量對象中訪問到的具體對象實際上是同一個。如圖所示。

因此當我改變n時,m也發生了變化。這就是引用類型的特性。

通過內存的角度來理解,是不是感覺要輕松很多?除此之外,我們還可以以此為基礎,一步一步的理解JavaScript的執行上下文,作用域鏈,閉包,原型鏈等重要概念。其他的我會在以后的文章慢慢總結,敬請期待。

六、內存空間管理

因為JavaScript具有自動垃圾收集機制,所以我們在開發時好像不用關心內存的使用問題,內存的分配與回收都完全實現了自動管理。但是根據我自己的開發經驗,了解內存機制有助于自己清晰的認識到自己寫的代碼在執行過程中發生過什么,從而寫出性能更加優秀的代碼。因此關心內存是一件非常重要的事情。

JavaScript的內存生命周期

1. 分配你所需要的內存
2. 使用分配到的內存(讀、寫)
3. 不需要時將其釋放、歸還

為了便于理解,我們使用一個簡單的例子來解釋這個周期。

var a = 20;  // 在內存中給數值變量分配空間
alert(a + 100);  // 使用內存
a = null; // 使用完畢之后,釋放內存空間

第一步和第二步我們都很好理解,JavaScript在定義變量時就完成了內存分配。第三步釋放內存空間則是我們需要重點理解的一個點。

JavaScript有自動垃圾收集機制,那么這個自動垃圾收集機制的原理是什么呢?其實很簡單,就是找出那些不再繼續使用的值,然后釋放其占用的內存。垃圾收集器會每隔固定的時間段就執行一次釋放操作。

在JavaScript中,最常用的是通過標記清除的算法來找到哪些對象是不再繼續使用的,因此a = null其實僅僅只是做了一個釋放引用的操作,讓 a 原本對應的值失去引用,脫離執行環境,這個值會在下一次垃圾收集器執行操作時被找到并釋放。而在適當的時候解除引用,是為頁面獲得更好性能的一個重要方式。

在局部作用域中,當函數執行完畢,局部變量也就沒有存在的必要了,因此垃圾收集器很容易做出判斷并回收。但是全局變量什么時候需要自動釋放內存空間則很難判斷,因此在我們的開發中,需要盡量避免使用全局變量。

要詳細了解垃圾收集機制,建議閱讀《JavaScript高級編程》中的4.3節

前端基礎進階系列目錄

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90524.html

相關文章

  • 進階1-3期】JavaScript深入之內存空間詳細圖解

    摘要:進階期理解中的執行上下文和執行棧進階期深入之執行上下文棧和變量對象但是今天補充一個知識點某些情況下,調用堆棧中函數調用的數量超出了調用堆棧的實際大小,瀏覽器會拋出一個錯誤終止運行。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,今天是第3天。 本計劃一共28期,每期重點攻...

    coordinate35 評論0 收藏0
  • 前端基礎進階目錄

    摘要:不過其實簡書文章評論里有很多大家的問題以及解答,對于進一步理解文中知識幫助很大的,算是有點可惜吧。不過也希望能夠對正在學習前端的你有一些小幫助。如果在閱讀中發現了一些錯誤,請在評論里告訴我,我會及時更改。 前端基礎進階(一):內存空間詳細圖解 前端基礎進階(二):執行上下文詳細圖解 前端基礎進階(三):變量對象詳解 前端基礎進階(四):詳細圖解作用域鏈與閉包 前端基礎進階(五):全方位...

    mo0n1andin 評論0 收藏0
  • 前端基礎進階(四):詳細圖解作用域鏈與閉包

    摘要:之前一篇文章我們詳細說明了變量對象,而這里,我們將詳細說明作用域鏈。而的作用域鏈,則同時包含了這三個變量對象,所以的執行上下文可如下表示。下圖展示了閉包的作用域鏈。其中為當前的函數調用棧,為當前正在被執行的函數的作用域鏈,為當前的局部變量。 showImg(https://segmentfault.com/img/remote/1460000008329355);初學JavaScrip...

    aikin 評論0 收藏0
  • 文章分享(持續更新)

    摘要:文章分享持續更新更多資源請文章轉自一前端文章基礎篇,,前端基礎進階一內存空間詳細圖解前端基礎進階二執行上下文詳細圖解前端基礎進階三變量對象詳解前端基礎進階四詳細圖解作用域鏈與閉包前端基礎進階五全方位解讀前端基礎進階六在開發者工具中觀察函數調 文章分享(持續更新) 更多資源請Star:https://github.com/maidishike... 文章轉自:https://gith...

    whlong 評論0 收藏0
  • 進階1-4期】JavaScript深入之帶你走進內存機制

    摘要:引擎對堆內存中的對象進行分代管理新生代存活周期較短的對象,如臨時變量字符串等。內存泄漏對于持續運行的服務進程,必須及時釋放不再用到的內存。 (關注福利,關注本公眾號回復[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,今天是第4天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃...

    不知名網友 評論0 收藏0

發表評論

0條評論

_Suqin

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<