javascript變量的做用域

基本類型和引用類型  
基本類型值指的是簡單的數據段,而引用類型值指的是那個可能由多個值組成的對象  
講一個值賦值給變量時,javascript解析器首先要肯定是基本類型仍是引用類型,基本數據類型能夠直接操做保存在變量中的值,而引用數據類型的值是保存在內存中的對象,在操做對象是,實際上操做的是對象的引用而不是實際的對象  javascript

變量的賦值
若是從一個變量上向另外一個變量上覆制__基本數據類型__的值,會在變量對象上建立一個新值,而後把該值複製到新變量的位置上,這個很好理解,來看下例子:java

var num1 = 5;
var num2 = num1;

  這是基本數據類型,而引用類型呢?其實一樣會將原來變量上的值複製一份到新的變量當中,只不過,複製的實際上是原來變量的一個指針,而這個指針指向存儲在堆中的一個對象。複製完成後,兩個變量都指向了堆中的同一個對象,因此改變其中一個的值,會對另一個產生影響。有如下代碼  web

var obj1 = new Object(); 
	var obj2 = obj1; 
	obj1.name = "Nicholas"; 
	alert(obj2.name);  //"Nicholas"

  傳遞參數
在javascript裏面,參數的傳遞都是按照`值類型來傳遞`的,即便你傳入的是一個引用類型瀏覽器

function setName(obj) {     
    obj.name = "Nicholas"; 
}  
var person = new Object(); 
setName(person); 
alert(person.name);    //"Nicholas"

 

 上面代碼的返回結果貌似參數是引用類型的傳遞,由於開始person對象沒有屬性,調用了setName方法以後,給參數obj加上了name參數,而後外面的person打印person.name居然是有值的,這是很明顯的引用傳遞的效果。可是不要被這種現象所迷惑,javascript在傳遞引用類型的參數的時候,只要這個參數不發生改變,那麼仍是按照引用類型來處理,可是隻有發生了改變效果就徹底不同了  

函數

function setName(obj) {     
    obj.name = "Nicholas";     
    obj = new Object();     
    obj.name = "Greg"; 
}  
var person = new Object(); 
setName(person); 
alert(person.name);    //"Nicholas" 

 



上面的例子能夠看出區別,若是真的是引用傳遞,那麼obj從新賦值,而且加上了name參數,最後person打印的應該是Greg的名字,可是結果倒是原來的值,只能說明javascript在這裏挖了一個大坑,很是的迷惑人,不過只要搞清楚這點就好了。 



 執行環境及做用域
執行環境(execution context)定義了函數或者變量有權訪問的其餘數據,決定了他們各自的行爲,每一個執行環境都有一個與之相關聯的變量對象,環境中定義的全部的變量和函數都保存在這個對象中  

全局執行環境是最外圍的執行環境,在web瀏覽器中,其實就是window對象,所以,全部全局變量和函數,都是做爲window的屬性和方法建立的,某個執行環境全部代碼執行完畢以後,該環境被銷燬,保存在其中的變量和函數定義也隨之被銷燬(全局執行環境直到應用程序退出,及瀏覽器關閉的時候纔會被銷燬)  

__每一個函數都有本身的執行環境__,當程序執行到一個函數時,函數的環境會被建立出來,進入當前程序的流程,而在函數執行完成以後,程序流程將其彈出並銷燬,把控制權返回給以前的執行環境

當代碼在一個環境中執行時,會建立變量對象的__做用域鏈__,其根本意義就是在不一樣層級的執行環境中,保證各個執行環境中的變量有序訪問,看看下面的代碼:spa

var color = "blue";  
function changeColor(){     
    var anotherColor = "red";  
    function swapColors(){         
        var tempColor = anotherColor;         
        anotherColor = color;         
        color = tempColor; 
        //在 swapColors函數裏面能夠訪問tempColor,anotherColor和color          
    } 
    //在這裏能夠訪問anotherColor和color,但不能訪問tempColor 
    swapColors(); 
}  

 




經過列子和圖,能夠看出,內部環境能夠經過做用域鏈訪問它之上的全部外部環境,可是外部環境不能訪問內部環境中的任何變量和函數。這些環境是線性的,有次序的。  

    每一個環境均可以向上搜索做用域鏈,以查詢變量和函數名;而任何環境都不能經過向下搜索做用域鏈而進入另外一個執行環境 

上面這段話很是重要,咱們來看下例子:指針

var color = "blue";  
function getColor(){     
    return color; 
}  
alert(getColor());  //"blue" 

 



很明顯,getColor函數裏面的color變量是從裏往外搜索到上級外部環境的color獲得的,如圖:  

在搜索的過程當中,若是出現同名的局部變量,這個搜索就會中止:code

var color = "blue";  
function getColor(){     
    var color = "red";     
    return color; 
}  
alert(getColor());  //"red"
相關文章
相關標籤/搜索