1. 程式人生 > >javascript:棧記憶體與堆記憶體淺談

javascript:棧記憶體與堆記憶體淺談

首先,我們來舉個爪子:

var m = 1;
var n = m;
n=2;
console.log(m);

大家覺得答案是什麼?是一的情自覺點贊,不開玩笑了,其實這個很簡單,對吧。那麼我們再來一個

var m = { a: 10, b: 20 }
var n = m;
n.a = 15;
console.log(m.a);

這回大家覺得答案是什麼?是15還是10?為什麼是15?

覺得有點蒙,那麼請聽我細細來講

對於基本資料型別還有引用型別,我上篇部落格已經講解了,而且也提到了棧記憶體與對記憶體,現在我們的重點就是這兩個


棧記憶體:
棧記憶體:後進先出(系統分配的)

什麼意思?就比如我們買一筒羽毛球,當我們打完球,肯定是要放回去,下回我們打的時候,肯定也是拿的第一個,最上面那個,對吧,相似的,

當我們定義了一個羽毛球為m,打完球了,我們放回去,放在棧裡,這時候他是最上面那個,所以我們下回也是拿那個m

當我們遇到對手了,想用黑色羽毛球一絕勝負,我們怎麼拿到放在最底層,珍藏多年的球?肯定要把最上面的球m拿出來,再拿第二個出來。。。。。最後拿到我們的那個球

這就是棧記憶體的後經先出,那到底什麼是棧記憶體?

棧記憶體在函式中定義的一些基本型別的變數和物件的引用變數都在函式的棧記憶體中分配。當在一段程式碼塊定義一個變數時,js就在棧中為這個變數分配記憶體空間,當超過變數的作用域後,js會自動釋放掉為該變數所分配的記憶體空間,該記憶體空間可以立即被另作他用。(百度百科)

這時候mark一下,下篇部落格在講解,先來了解下什麼是堆記憶體

堆記憶體

現在我們桌面上有很多本書,散亂的放著,我們要拿起其中一本書,我們不需要動到其他的書籍,這時候就是堆記憶體,畢竟是一堆書嘛

堆記憶體是區別於棧區、全域性資料區和程式碼區的另一個記憶體區域。堆允許程式在執行時動態地申請某個大小的記憶體空間。

現在回顧最開始的那個問題,請先記死一句話“
js不允許去直接使用堆記憶體,所以操作的時候我們是操作的是棧的物件,而不是直接操作記憶體的物件


什麼意思?不懂是吧,沒關係,我們來開局第一個例子,首先,我們定義了一個變數a,但是按照這句話的意思,我們不是直接劃分了一個區間為1


的,名字為a的空間,而是劃分了一個空間用來儲存我們的變數1,然後再建設一個路標,一個指標,一個針眼,一個a去告訴我們那個資訊在哪兒,然後!當我們使得b=a的時候,我們把那個路標,針眼又差了一遍,接著!我們修改了b=4;這是什麼意思?直接修改了b所指向的那個名字叫1的空間嗎?很明顯不可能。為什麼?因為
js不允許去直接使用堆記憶體,所以操作的時候我們是操作的是棧的物件,而不是直接操作記憶體的物件

那我們只能是再去創造一個空間,那麼這時候a和b所指向的空間完全不同!那麼答案肯定就是不一樣,但是這裡我們也注意到了,他只是個路標,一個針眼,請記住,一個針眼最貴是75塊錢


接著,第二道題,我們一樣的解析,但是注意!

a: 10, b: 20

這一部分是存放在哪兒的?對記憶體的,真的嗎?,真正的流程是這樣的我們通過var n = m執行一次複製引用型別的操作。引用型別的複製同樣也會為新的變數自動分配一個新的值儲存在變數物件中,但不同的是,這個新的值,僅僅只是引用型別的一個地址指標。當地址指標相同時,儘管他們相互獨立,但是在變數物件中訪問到的具體物件實際上是同一個。所以最終就出現了呢個結局。


對於堆記憶體,你可以理解為他是一個自帶針眼的大野刀,它既有針眼的功能,又是有吸血,回南的基本功能,還可能有攻速,法強等,所以我身上帶著個眼石,和打野刀,哪個更輕?哪個更快捷?哪個功能更全面?


當前,瞭解這些還是不夠的,我們還需要了解js更多的底層,比如我們最常遇到的作用域,這個下回再講,我去打野了