變量的生命周期
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對象的形式。
#本文有寫的不好或不對的地方還請各位指出,一起學習!#
