js變量的生命周期


變量的生命周期

 

1.聲明

全局變量:全局聲明的變量
局部變量:函數內聲明的變量,函數參數


聲明局部變量的時候必須用var,否則產生的是全局變量

1 scope = "global";
2 function checkscope2() {
3     scope = "local";
4     myscope = "local";
5 }
6 checkscope2();
7 console.log(scope);//輸出local,全局變量被修改
8 console.log(myscope);//輸出local,全局命名空間被搞亂了

使用var聲明的變量是不可配置的,即無法通過delete運算符刪除

 
1 var truevar = 1;//不可配置的全局變量
2 fakevar = 2;
3 this.fakevar2 = 2;
4 delete truevar;//出錯
5 delete fakevar;//執行成功
6 delete this.fakevar2;//執行成功

 

在函數內部中局部變量會遮蓋同名的全局變量

 
1 var scope = “global”;//聲明一個全局變量
2 function checkscope(){
3     var scope = “local”;//聲明一個同名的局部變量
4     console.log(scope);//輸出”local”
5 }
 

2.變量提升(變量聲明提前)

即函數中聲明的所有變量都被“提前”至函數體的頂部,這步操作是在代碼開始運行之前的JavaScript引擎預編譯時執行的。 
例:

 
1 var scope = “global”;
2 function f(){
3   console.log(scope);//輸出”undefined”,而不是”global”
4   var scope = “local”;//變量在這里聲明且賦初值,但變量本身在函數體內任何地方均是有定義的
5   console.log(scope);//輸出”local”
6 }

實際上,上述的代碼等價於:

1 var scope = “global”;
2 function f(){
3   var scope
4    console.log(scope);//輸出”undefined”,而不是”global”
5    scope = “local”;//變量在這里聲明且賦初值,但變量本身在函數體內任何地方均是有定義的
6    console.log(scope);//輸出”local”
7 }
 

3.全局變量與局部變量的作用域

全局變量:當聲明一個全局變量時,實際上是定義了全局對象window的一個屬性,在任何地方都可以對其進行訪問

局部變量:局部變量在聲明它的函數體內以及其所嵌套的函數體內是有定義的。

作用域鏈:

 
 1 var color = "blue";
 2 function changeColor(){
 3     var anotherColor = "red";
 4     function swapColors(){
 5         var tempColor = anotherColor;
 6         anotherColor = color;
 7         color = tempColor;
 8         // 這里可以訪問 color、anotherColor和tempColor
 9     }
10     //這里可以訪問color和anotherColor,但不能訪問tempColor
11     swapColors();
12 }
13 // 這里只能訪問 color changeColor();        

矩形表示特定的執行環境 
其中,內部環境可以通過作用域鏈訪問所有的外部環境,但 外部環境不能訪問內部環境中的任何變量和函數。。每個環境都 可以向上搜索作用域鏈,以查詢變量和函數名;但任何環境都不能通過向下搜索作用域鏈而進入另一個執行環境。

對於上面的例子而言,其作用域鏈中包含 3個對象:swapColors()的變 量對象、changeColor()的變量對象和全局變量對象。swapColors()的局部環境開始時會先在自己的 變量對象中搜索變量和函數名,如果搜索不到則再搜索上一級作用域鏈,即changeColor()的作用域鏈 

作用域鏈的延長 :

 
 1 var outer = {
 2     value : "outer",
 3     index : 0
 4 }
 5 function test() {
 6     var inner = "inner";
 7     with(outer){//將outer對象添加到此作用域,可以在其中直接使用其方法和屬性
 8         value = inner;
 9     }
10 }
11 test();
12 console.log(outer.value);//輸出"outer"

除了with,我們還可以使用catch延長作用域鏈

5.垃圾回收

標記清除(常用):

工作原理:是當變量進入環境時,將這個變量標記為“進入環境”。當變量離開環境時,則將其標記為“離開環境”。標記“離開環境”的就回收內存。

工作流程:

1.垃圾回收器,在運行的時候會給存儲在內存中的所有變量都加上標記。

2.去掉環境中的變量以及被環境中的變量引用的變量的標記。

3.再被加上標記的會被視為准備刪除的變量。

4.垃圾回收器完成內存清除工作,銷毀那些帶標記的值並回收他們所占用的內存空間。

引用計數:

工作原理:跟蹤記錄每個值被引用的次數。

工作流程:

1.聲明了一個變量並將一個引用類型的值賦值給這個變量,這個引用類型值的引用次數就是1。

2.同一個值又被賦值給另一個變量,這個引用類型值的引用次數加1.

3.當包含這個引用類型值的變量又被賦值成另一個值了,那么這個引用類型值的引用次數減1.

4.當引用次數變成0時,說明沒辦法訪問這個值了。

5.當垃圾收集器下一次運行時,它就會釋放引用次數是0的值所占的內存。

弊端:在循環循環引用中變量的引用次數不會為零則變量不會被回收

 
1 function test(){
2     var a={};
3     var b={};
4     a.prop=b;//a的引用次數為2
5     b.prop=a;//b的引用次數為2
6 }

 

而為了解決這種問題,可以顯性地切斷引用,即將變量的值設為null

現在大部分的瀏覽器都是采用標記清除的垃圾回收機制,而IE的BOM和DOM中的對象是以引用計數方式進行垃圾回收的COM對象的形式存在的,所以會有導致變量不能被回收的現象。但是在IE9之后就取消了COM對象的形式。

 

#本文有寫的不好或不對的地方還請各位指出,一起學習!#


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM