變量做用域、聲明提早、做用域鏈

恩,快要下班了,我先撿重要的說奧javascript

一、首先了在函數體內 "局部變量" 優先於 "全局變量" ,這其實算是廢話了html

var a = 'aa';
        var test = function(){
            var a = 'bb';
            alert(a);
        }
        test();

 

二、js無塊級做用域,至於這塊級做用域,你們能夠想一想C語言,PHP之類,"{}"之中定義的,外面是看不到了,可是JS就不是了,例如java

 

for(var i = 0; i < 5; i++){

        }
        alert(i);

 

三、聲明提早(此處有讀者發現錯誤,如今進行改正)閉包

var a = 'aa';
function test(){
  alert(a);//undifined
  var a = 'aa';
}

上述是由於聲明提早所致,js執行分爲兩段,第一段先解釋,第二段纔開始執行, 因爲局部變量優先級高於全局變量,因此函數自己先回訪問局部變量中的'a',在調用'alert'以前局部變量中的'a'爲'undefined',,上述代碼解釋後的結果等價於下方函數

 
 
var a = 'aa';

function test(){
var a = undefined; alert(a); a = 'aa'; }

 

上面那段代碼其實還有更加深奧的解釋,好比‘湯姆大叔’這篇 深刻理解JavaScript系列(2):揭祕命名函數表達式 spa

 

四、做用域鏈code

又來到了這個高大上的話題,什麼是做用域鏈?htm

對象

每一段js代碼(全局代碼和函數)都有一個與之關聯的做用域鏈,這個做用域鏈是一個對象列表或者鏈表,這組對象定義了這段代碼‘做用域中的變量’,當js須要查找變量x的值得時候(變量解析),它會從鏈的第一個對象開始查找,若是這個對象有個一個名爲x的屬性,則直接使用這個屬性的值,若是不存在x屬性,js會查找鏈上的下一個對象,若是仍然沒有則繼續下一個對象,以此類推。若是該鏈上沒有任何一個對象用於x屬性,那麼就認爲該段代碼做用域鏈上不存在x,最終拋出一個引用異常錯誤blog

下面咱們用一段代碼來闡述這個話題

var a = 'aa';
var test = function(){
   alert(a);  
}

var test1 = function(){
  var a = 'bb';
  test();
}

test1();

上面一段代碼雖然在函數'test1'裏面從新定義了變量'a'可是函數 'test'仍然彈出'aa', 這個就能夠用'做用域鏈'理論來解釋這個現象

對於函數'test'而言,它的做用域鏈應該是 'global' 全局做用域對象和函數'test'自己做用域對象,'global'全局做用域對象在外層,'test'自己做用域對象在內層,'global'全局做用域對象上有一些屬性,其中就包括變量'a'、'test'、'test1',固然其內部機制確定有指定該變量是什麼類型、什麼值的地方,這裏咱們暫且不去探討。以此類推,函數'test1'的做用域鏈是'global'鏈再加上其自己做用域對象,其自己做用域對象屬性中包括變量'a'。那麼在執行函數'test'的時候,'test'天然會在本身的做用域鏈上查找變量屬性,而不會跑到'test1'的做用域鏈上查找屬性,這時'test'的做用域鏈上恰好有'a'屬性,其值爲'aa'。 還記得我當初那篇"javascript中的閉包,超簡單論述,保證小學生必懂" 文章嗎,裏面也有有關做用域鏈和閉包的解釋。另外,還有一篇比較高深的,"湯姆大叔" 的 "深刻理解JavaScript系列(14):做用域鏈(Scope Chain)" ,能夠去瞅瞅,不過是否能懂,就看造化了!

 

鄙人才疏學淺,有不足之處,歡迎補足!

相關文章
相關標籤/搜索