02變量,作用域,內存問題


1.基本類型和引用類型的值
基本類型是保存在棧內存中的簡單數據段,這種值完全保存在內存中的一個位置,而引用類型是指保存在堆內存中的對象,變量中保存的實際上是一個指針,這個指針指向內存中的另一個位置,該位置保存對象。


將一個值賦值給變量時,解析器必須確定這個值是基本類型還是引用類型,五種基本類型的值在內存 中分別佔有固定大小的空間,因此可以將他們保存在棧內存中,這樣可以提高查詢變量額速度,對於基本類型值的變量,他們是按值訪問的,我們操作的是實際保存的值。


如果賦值變量是一個引用類型的值,則必須在堆內存中爲這個值分配空間,這種值的大小不固定,因此不能保存在棧內存中,但是內存地址的大小是固定的,因此內存地址保存在棧內存中,這種訪問叫做按引用訪問。




2.動態屬性:
可以給引用類型動態的添加屬性
var person = new Object();
person.name="Mike";


3.複製變量值
基本類型:從一個變量向另一個變量複製基本類型的值,會在棧中創建一個新的值,然後把該值複製到新變量分配的位上。這兩個變量不會互相影響。


引用類型:同樣也會將存儲在棧中的值複製一份到新的變量分配的空間,不同的是,這個值複本其實是一個指針,複製結束後,兩個變量指向同一個對象,改變一個會影響到另一個。




3.傳遞參數
ECMAScript所有的函數參數都是按值傳遞的,也就是說把函數外部的值複製給函數內部的參數。
向參數傳遞基本類型的值的時候,被傳遞的值會被複制給一個局部變量,在向參數傳遞引用類型時,會把這個值在內存中的地址複製給一個局部變量,因此這個局部變量的變化會反映的函數的外部。
function setName(obj){
obj.name = "Mike";
obj = new Object();
obj.name ="Greg";
}


var person =new Object();
setName(person);
alert(person.name);//"Mike"
如果是按引用傳遞,那麼person會被修改指向其name爲greg的新對象,但是在訪問person.naem的時候,顯示Mike,這說明即使在函數內部修改了參數的值,,但原始引用沒有改變,實際上在函數內部重寫obj時,這個變量的引用就是一個局部變量了,這個局部對象會在函數執行結束後立即被銷燬。




4.檢測類型
instanceof




5.執行環境與作用域


執行環境定義了變量或函數有權訪問的其他數據,決定了它們各自的行爲,每個環境變量都有一個與之相關的變量對象,環境變量中所有的變量和函數都保存在這個對象中,雖然代碼無法訪問到這個對象但是解析器在處理數據時會在後臺使用它。


全局執行環境是最外圍的一個執行環境,在web瀏覽器中,全局執行環境爲window對象,因此所有全局變量和函數都是最爲window對象的屬性和方法創建的,某個執行環境中的所有代碼執行完畢後,該環境被銷燬,保存在其中的所有變量和函數定義也隨之銷燬。


每個函數都有自己的執行的執行環境,當執行流進入一個函數時,函數的環境會被推入一個環境棧中,函數執行後,棧將其環境彈出,把控制權返回給之前的執行環境。


當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈,作用域鏈的用途是保證對執行環境有權訪問的所有變量和函數的有序訪問,作用域的前端,始終是當前執行的代碼所在環境的變量對象,如果這個環境是函數,則將其活動對象作爲變量對象,活動對象在開始時只包含一個變量-arguments對象,作用域鏈的下一個變量對象來自包含環境,再下一個變量對象來自下一個包含環境,這樣一直延續到全局執行環境,全局執行環境的變量對象始終是作用域鏈的最後一個對象。


標示符解析式沿着作用域鏈一級一級搜索標示符的過程,搜索過程從作用域鏈的前端開始然後逐級回溯,直到找到爲止。


當進入catch和with語句時,作用域鏈會被延長。






6.沒有塊級作用域
  第一種:聲明變量:在使用var聲明變量的時候,這個變量被自動添加到距離最近的可用環境中,對於函數而言,這個最近的環境就是函數的局部環境,如果變量在未經聲明的情況下被初始化,那麼該變量會被自動添加到全局變量。
  第二種:查詢標識符:




<html>
<head>
<script type="text/javascript">
    function test(o) {
var i = 0;
if (typeof o == "object") {
var j = 0;
for (var k = 0; k < 10; k++) 
{
document.write(k);
}
document.write(k);  //還可以訪問到k爲10
}
document.write(j); //還可以訪問到j爲0
}
var o = new Object();
test(o);
</script>
</head>
</html>






<html>
<head>
<script type="text/javascript">
   var scope = "global";
   function f() {
  alert(scope);  //顯示undefined
  var scope = "local";
  alert(scope);
   }
   f();
</script>
</head>
</html>




7.垃圾收集
函數中局部變量的正常生命週期:局部變量只在函數執行的過程中存在,而在這個過程中,會爲局部變量在棧內存或者堆內存中分配相應的空間,然後在函數中使用這些變量,直到函數結束,垃圾收集器必須跟蹤哪個有用哪個沒用,對於不再有用的變量打上標記,對於標示無用對的策略可能會因現實而異,通常有兩個策略。
第一種:標記清除:
第二種:引用計數:

























































發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章