JavaScript語言是一門優秀的腳本語言.其中包含腳本語言的靈活性外還擁有許多高級語言的特性.例如充許構建和實例化一個對象,垃圾回javascript
收機制(GC:Garbage Collecation).一般咱們使用new建立對象,GC負責回收對象佔用內存區域.所以瞭解GC,能夠加深對JavaScript垃圾回收html
機制的理解。java
1.用局部變量和全局變量解釋GC程序員
GC在回收內存時,首先會判斷該對象是否被其它對象引用.在肯定沒有其它對象引用便釋放該對象內存區域.所以如何肯定對象再也不被引用是算法
GC的關鍵所在.數組
1. <script> 數據結構
2. function aa(){ 函數
3. this.rr = "彈窗"; this
4. } spa
5. function bb(){
6. this.rr = "彈窗";
7. }
8.
9. var b1;
10. function cc(){
11. var a1 = new aa();
12. b1 = new bb();
13. return b1;
14. }
15.
16. cc();
17. alert(b1.rr)
18. </script>
如上代碼中,執行完cc()後a1被回收了,此後咱們能夠經過b1.rr彈出文字窗口.在一些基礎書籍中解釋爲:a1爲局部變量,b1是全局變量.局部
變量執行完後會被GC回收.但不全是這樣,以下代碼:
1. <script>
2. function aa(){
3. this.rr = "彈窗";
4. }
5. function bb(){
6. this.rr = "彈窗";
7. }
8.
9. function cc(){
10. var a1 = new aa();
11. var b1 = new bb();
12. return b1;
13. }
14.
15. var b1 = cc();
16. alert(b1.rr);
17. </script>
此時cc函數中的 a1,b1都是局部變量,但仍然會彈出文字窗口.說明b1並無被GC回收.所以JavaScript中局部變量不是全部時候都被GC回收的.
2.抽象理解GC
GC回收機制還須要近一步瞭解。在此時引入幾個概念:雙向鏈表,做用域鏈,活動對象(爲了方便理解,簡化了原文的概念
[http://softbbs.pconline.com.cn/9497825.html]), 其中雙向鏈表描述複雜對象的上下層級關係. 做用域鏈與活動對象分別是雙向鏈表
中的某個節點.以函數cc爲例變量層級關係爲:
1. window<=>cc<=>a1<=>rr
2. <=>b1<=>rr
(原文有詳細解釋)在執行cc()方法時,內存中變量的引用關係如上圖,文字解釋以下:
window的活動對象包括cc,假設window是頂級對象(由於運行中不會被回收)
cc的活動對象包括a1和b1,其做用域鏈是window
a1的活動對象包括rr,其做用域鏈是cc
b1的活動對象包括rr,其做用域鏈是cc
執行cc()時,cc的執行環境會建立一個活動對象和一個做用域鏈.其局部變量a1,b1都會掛在cc的活動對象中.當cc()執行完畢後,執行環境
會嘗試回收活動對象佔用的內存.但因局部變量b1 經過return b1,爲其增長了一條做用域鏈:window<=>b1<=>rr,因此GC中止對b1回收.
所以若是想將一個局部變量/函數提高爲全局的,爲其增長一條做用域鏈就OK了。
同時控制好對象的做用域鏈也變得重要了.因做用域鏈會意外致使GC沒法回收目標對象.例如:
1. <SCRIPT LANGUAGE="JavaScript">
2. <!--
3. //貓
4. function cat(name){
5. var zhuren ;
6. this.name = name;
7.
8. //設置主人
9. this.addZhuRen = function(zr){
10. zhuren = zr;
11. }
12.
13. this.getZhuRen = function(){
14. return zhuren;
15. }
16. }
17.
18. //主人
19. function zhuren(name){
20. this.name = name;
21. }
22.
23. //建立主人:
24. var zr = new zhuren("zhangsan");
25. //建立貓
26. var cat1 = new cat("asan");
27. //設置該貓的主人
28. cat1.addZhuRen(zr);
29. //釋放主人
30. zr = null ;
31. //此處還存在對主人對象的引用
32. alert(cat1.getZhuRen().name)
33. //-->
34. </SCRIPT>
瞭解javascript的人都知道數據的基本類型按大的分類有兩種:原始值和引用值
在研習算法的時候會過多的和內存打交道;理解棧和堆的定義是很重要的,算法就是爲了可以得到最大的效率
任何語言都是如此,javascript也不例外;在javascript中,我在把變量類型分爲原始類型和引用類型。原始類型是放在棧即內存中,而引用類型這是放在堆中。在ECMAscript中,也是這麼定義的。
棧
主要做用表現爲一種數據結構,是隻能在某一端插入和刪除的特殊線性表。它按照後進先出的原則存儲數據,先進入的數據被壓入棧底,最後的數據在棧頂,須要讀數據的時候從棧頂開始彈出數據(最後一個數據被第一個讀出來)。
棧是容許在同一端進行插入和刪除操做的特殊線性表。容許進行插入和刪除操做的一端稱爲棧頂(top),另外一端爲棧底(bottom);棧底固定,而棧頂 浮動;棧中元素個數爲零時稱爲空棧。插入通常稱爲進棧(PUSH),刪除則稱爲退棧(POP)。棧也稱爲後進先出表。在這裏用數組進行模擬棧的特性
棧能夠用來在函數調用的時候存儲斷點,作遞歸時要用到棧!
var arr=[];//建立一個數組模擬棧 arr.push("a");//壓入元素a arr.push("b");//壓入元素b arr.pop();//彈出元素a arr.pop();//彈出元素b arr.push("c");//壓入元素c |
圖譜解釋:
從上圖能夠看出棧有着先進後出的特性;在棧中的數據直接能夠訪問,效率比較高
堆:
在程序中,堆用於動態分配和釋放程序所使用的對象。在如下狀況中調用堆操做:
1.事先不知道程序所需對象的數量和大小。
2.對象太大,不適合使用堆棧分配器。
堆使用運行期間分配給代碼和堆棧之外的部份內存。
在javascript中,引用數據是放在堆中的,例如數組和對象,由於在javascript中,一切都是對象,對象能夠進行擴展,放置在堆中能夠進 行不斷的擴展,若是放在內存中就會消耗大量資源。放置在堆中的數據的查詢效率比較低。這也是內存優於堆的好處,可是內存的存儲空間要比堆的小不少。
function Car(id,name,price) { this.id=id; this.name=name; this.price=price; } var num=24; var str="car"; var bol=false; var obj={}; var arr=[1,2,3]; var car=new Car(1,"benze",230000); |
圖譜解釋:
這樣很清楚的知道棧和堆的區別;原始類型的數據放在棧中,引用類型的數據放在堆中。引用類型的數據同C中的指針很相似,咱們不能直接操做堆中的數據,咱們經過一個指針來引用這些數據進行操做,看以看做是遠程操控。
棧與堆的區別:
1 效率的不一樣
棧的效率比堆要高,棧中的數據直接可使用,而對則須要經過引用來進行操做,即棧的速度比堆快
2 空間存儲不一樣
堆的存儲空間要比棧大
3 放置數據類型的不一樣