第4章 變量、做用域和內存---JS紅寶書書摘系列筆記

1、基本類型和引用類型前端

       ECMAScipt變量可能分爲兩種數據類型:基本類型和引用類型。瀏覽器

                基本類型:指簡單的數據段;包括Undefined、Null、Boolean、Number、String;能夠操做保存在變量中值(棧內存),因此稱爲按值訪問;不能添加屬性。函數

                引用類型:可能由多個值構成的對象;包括Arry、Object等;js不容許直接操做對象的內存(堆內存)空間,因此成爲按引用訪問;能夠動態得添加/改變/刪除引用類型值的屬性和方法。性能

      1.複製spa

 1   var a=5;
 2   var b=a; 3 console.log(a);//5 4 console.log(b);//5 5 a=3; 6 console.log(a);//3 7 console.log(b);//5 8 var arrA=[1,2,3]; 9 var arrB=arrA; 10 console.log(arrA);//[1,2,3] 11 console.log(arrB);//[1,2,3] 12 arrA[0]='x'; 13 console.log(arrA);//['x',2,3] 14 console.log(arrB);//['x',2,3]
   上述代碼中a、b爲基本數據類型,arrA、arrB爲引用類型。能夠看出首先定義並初始化了變量a爲5,再定義變量b,此時打印出來a和b都是5;改變a的值爲3,再次打印,a爲3,b爲5。對於引用類型arrA以及arrB,進行相似的操做,會發現arrA和arrB的值保持一致。繼續看以下代碼
1   var arrC=[1,2,3];
2   var arrD=arrC; 3 console.log(arrC);//[1,2,3] 4 console.log(arrD);//[1,2,3] 5 arrC=['X','Y','Z']; 6 console.log(arrC);//['X','Y','Z'] 7 console.log(arrD);//[1,2,3]

        此時引用類型arrC、arrD的值並無改變。這是由於基本類型是在變量對象上,而引用類型是保存在內存中。基本類型的變量是徹底相互獨立的,而引用類型變量的複製拷貝的實則上是一個指針,這個指針指向存儲在內存中的對象。只要指針是指向改變的對象時,則經過這些指針訪問的也會發生改變,如arrA、arrB。而arrC與arrD之因此先後沒有保持一致,是由於arrC=['X','Y','Z']這個操做,是將arrC的指針指向了另外一個對象,即['X','Y','Z']。而arrD的指針的指向並無發生改變,仍然指向[1,2,3]。指針

       2.傳遞參數code

          函數的參數傳遞是按值傳遞的,不管是基礎類型仍是引用類型。這一點書上說的很詳細,能夠參考書上P71頁。對象

      3.檢測類型blog

         typeof用來檢測基本數據類型,instanceof用來檢測引用類型。由於引用類型的值都是Object的實例,因此instanceof檢測引用類型和object構造函數時返回true;反之instanceof檢測基本類型時,因爲基本類型不是對象,因此始終返回false。ip

2、執行環境及做用域

      Web瀏覽器中,全局執行環境被認爲是window對象,因此全部全局變量和函數都是做爲window對象的屬性和方法建立的,不過通常省略了window。我的感受這一小節內容仍是比較容易理解的,執行環境就只分爲兩種:全局和局部。

     1.延長做用域鏈

        兩種方法:try-catch和with語句。因爲witch語句會給性能帶來影響,因此之前者爲例,catch語句會在做用域鏈的前端添加一個變量對象A,其中包含的是被拋出錯誤對象的申明,即在catch語句內部,能夠引用對象A的屬性或方法。

     2.JS語言沒有塊級做用域

        因爲訪問局部變量不用向上搜索做用域鏈,因此訪問局部變量要比訪問全局變量要快。即便快的不明顯,可是仍然要儘可能避免使用全局變量,防止變量污染。

3、垃圾收集

       JS具備自動垃圾收集機制,所需內存的分配以及無用內存的回收徹底實現了自動管理。其原理是:垃圾收集器會按照固定的時間間隔週期性地找出那些再也不繼續使用的變量,而後釋放其佔用的內存。局部變量在函數執行完畢時會自動被銷燬。

    1.JS垃圾收集方式有兩種:標記清除和引用計數。

       前者最經常使用,簡單來說,垃圾收集器會給存儲在內存中的全部變量加上標記,即進入執行環境的變量(佔用內存)會被加上一個標記表示不會被清除;當變量要離開環境,執行完畢時,這些變量會再次被標記表示要被清除,此時環境中的變量已經訪問不到這些變量。

       引用計數是指跟蹤記錄每一個值被引用的次數。當聲明一個變量並將一個引用類型賦值給該變量時,其引用次數爲1,若是同一個值又被賦給另外一個變量,則該值的引用次數家1;相反,若是包含對這個值引用的變量又取到另一個值,則引用次數減1.當內存中值的引用次數爲0時,其佔用的內存空間會被回收。通俗來說,引用次數就是指向內存對象的指針的個數。能夠類比前面的arrC和arrD,以下圖:

1 1   var arrC=[1,2,3];
2 2   var arrD=arrC;
3 3   console.log(arrC);//[1,2,3]
4 4   console.log(arrD);//[1,2,3]
5 5   arrC=['X','Y','Z'];
6 6   console.log(arrC);//['X','Y','Z']
7 7   console.log(arrD);//[1,2,3]

       首先內存中的值爲[1,2,3],當聲明arrC並將值[1,2,3]賦給arrC時,值的引用次數爲1,即arrC的指針指向它。當將arrC的值賦給arrD時,值[1,2,3]的引用次數+1爲2,此時arrC、arrD的指針都指向值[1,2,3]。接下來,將值['X','Y','Z']賦給arrC時,arrC的指針再也不指向值[1,2,3],而是指向值['X','Y','Z'],此時arrD依舊指向值[1,2,3]。值[1,2,3]的引用次數減1爲1。引用計數最大的弊端就是循環引用,即兩個對象都包含指向對方的引用。

   2.性能問題

      垃圾收集器是週期運行的,時間間隔的肯定會影響瀏覽器的性能。

  3.管理內存

     解除引用:將數據的值置爲null,適用於大多數全局變量和全局對象的屬性,其做用是讓值脫離執行環境,以便垃圾收集器下次運行時將其回收。

相關文章
相關標籤/搜索