堆棧內存的分析以及做用域的詳解

堆和棧

棧內存和堆內存的概念和做用

js的內存機制主要分紅兩種,一個是棧內存,一個是堆內存。數組

棧內存有兩個做用瀏覽器

1,給js代碼提供自上而下的運行機制,全部的js代碼都是在棧內存運行的。 2,由於基礎類型比較簡單,因此棧內存會直接開闢一個空間把基礎類型保存在棧內存裏邊。 當棧內存被銷燬,存儲在棧內存中的基本類型的值也會被銷燬掉。bash

堆內存的做用: 存儲引用類型的值,是以鍵值對的方式存儲的。 若是堆內存釋放了,則引用就完全消失了。函數

堆內存的釋放?

當堆內存沒有被任何的變量或者其餘的東西佔用,谷歌瀏覽器(標準的瀏覽器)會在空閒的時候自動進行內存的回收。把不被佔用的內存銷燬掉。 谷歌瀏覽器是每隔一段時間進行內存的釋放。 Ie瀏覽器是計數的方式,當有一個變量引用這個堆內存地址時,則計數爲1,若是兩個變量引用則計數爲2,以此內推,當計數爲0,也就是沒有變量引用的時候,這個堆內存就會被釋放。spa

內存泄漏code

ie瀏覽器堆的堆內存是以計數的方式實現的,可是有的時候計數會出現混亂,致使計數一直不爲0,因此就不會銷燬,這種狀況就叫作內存的泄露。cdn

代碼對內存釋放的操做:對象

let a=引用地址A,若是把a=null,而且這引用地址A只有a引用,那麼把a=null時,就是把變量a的引用變成爲null。這時引用地址A就失去了引用變量。那麼在標準瀏覽器中空閒的時候會銷燬掉這個失去引用變量的引用地址的堆內存,或者ie瀏覽器已經發現失去了最後一個引用的變量,也會銷燬掉這個引用地址的堆內存。blog

基礎類型【變量的提高】:

瀏覽器在加載頁面的時候,會開闢一個全局的做用域,在這個全局的做用域中自上而下的執行程序代碼。內存

在執行的過程中會遇到var關鍵字聲明的變量

如:var a=1;

這行代碼會有3個步驟,分別是:

1,var a;聲明一個變量,此時的變量的值是undefined

2,在全局做用域下存儲1

3,把這個1(值)和變量a關聯起來,咱們通常把這個操做叫作定義或者是賦值。

若是遇到值爲基礎類型的變量的賦值,其實操做的是賦值的變量的值: 如: var b=a; b=2;

分析:var b=a;//其實b和a是沒有關係的,實際上是b=1;直接等於a的值,這個1一樣是存在全局做用域裏邊。因此目前全局做用域裏邊村了兩個1。

分析:b=2;//一個變量只能有一個值,因此 2存在全局做用域下,而且2和b相關聯。而以前的b與1相關聯會破裂掉,此時被破裂掉的1由於沒有任何變量與它關聯,因此會被回收掉。

【引用類型】:

由於引用類型比較複雜,因此引用類型的值會在堆內存中開闢一個空間存儲值。

例如,實例-1

var ary1=[1,2,3];
        var ary2=ary1;
        ary2.push(100);
        console.log(ary1);//[1,2,3,100]
        
        
複製代碼

圖解

文字理解

1,首先理解如下堆和棧的概念,棧和堆都是瀏覽器運行時分配的內存存儲區域。 棧主要是存儲變量和基礎類型的值,堆存儲的是複雜的數據,通常都是對象。

全局做用域就是在棧內存中開闢的。

2,棧內存的變量和堆內存中的對象之間的關聯是用引用地址進行關聯的。具體是,當對象生成時會在堆內存中開闢一個存儲的空間,同時生成一個16進制的地址。而後再把這個地址賦值給棧內存的變量。那麼這個變量經過引用這個地址到堆內存中尋找這個對象,而後進行操做。

上述實例分析

1,當全局做用域執行 var ary1=[1,2,3]時,會在全局做用域下開闢一個空間存儲ary1變量。而後再到堆內存裏邊生成數組對象進行存儲([1,2,3])。再把對象生成的地址(xxxfff)賦值給ary1。

2,var ary2=ary1時,就是ary1的引用值(xxxfff)賦值給ary2.這時的ary2一樣能夠到堆內存中尋找這個地址所對應的對象。

3,ary2.push(100)操做時,操做的就是地址xxxfff對應的對象。

4,console.log(ary1);ary1的和ary2的值都是xxxfff,因此兩個在堆內存中的對象是同一個。

若是對象是函數

若是是函數會分紅兩個步驟: 第一個步:是當函數定義的時候,會把函數名以變量的形式保存在棧內存中,而函數體相對來講比較複雜,因此是以字符串的方式保存在堆內存中,而後把對內存中的地址賦值給棧內存中的變量。 第二步:函數的執行的時候,會在棧內存中又開闢一個做用域,而後在這做用域中執行函數在堆內存中的函數體。執行的方式和在全局做用域下是同樣的。

實例分析

var a=1;
        function sum(){
            var b=2;
            console.log(a+b);
        }
        sum();//3
        sum();//3
複製代碼

圖解

文字理解: 1,在全局做用域下存儲變量和賦值的引用地址,堆內存中存儲函數體,而且函數體是以字符串的方式進行存儲的。

2,函數在執行的時候,開闢一個新的做用域,若是函數執行屢次就會開闢多個做用域,因此這裏sum函數開闢了兩個做用域。函數做用域和全局做用域執行操做是同樣的。

注意:若是函數執行屢次則會在棧內存中開闢多個做用域。

相關文章
相關標籤/搜索