js的變量,變量做用域,做用域鏈

變量聲明: 使用var關鍵字聲明,若是使用沒有聲明的變量,則JS會自動聲明此變量根據變量做用域。若是變量只聲明爲賦值,則此時值是undefined。重複聲明變量,在JS不會報錯,會依據最後一次的聲明來處理變量。 變量做用域: 一個變量的做用域是,程序代碼定義這個變量的區域,全局變量在程序代碼內任何地方均可以訪問。 包括在{}函數,對象內的變量(屬性)成爲局部變量。 在函數體內定義的變量成爲局部變量,做用域也是局部,函數參數也是局部變量。 他們只在函數體內有意義。 在函數體內,局部變量優先於全局變量,也就是說當局部變量與全局變量重名時,會優先使用局部變量。在函數體內定義變量時必定要使用var關鍵字,或者JS會查早同名全局變量並使用。 函數能夠嵌套,父函數定義的變量能夠在子函數內有意義。 Var space=’op’; Function par(){ Var space = ‘par’; Function son(){ Return space; } } Par(); // => par Var space=’op’; Function par(){ Var space = ‘par’; Function son(){ Var space = ‘son’; Return space; } } Par(); // => son 函數變量做用域和聲明提早。 變量聲明在這個函數體內以及這個函數嵌套的任意函數體內都是有定義。 JS的函數做用域意味着:定義的變量在函數體內是始終是可見,這意味這變量在在函數體內聲明以前就可使用。 Var space =’global’; Function test(){ Console.log(space); //=>undefined 變量雖有定義可是沒有值 Var space;space=’function’; //變量在這裏賦予初始值,可是變量在函數體內都是有定義的(var space); Console.log(space); //=> function 變量以賦予初始值 } 注意:因爲函數做用域的做用,在函數體內的定義變量,在函數內始終有定義,也就是說JS在檢測函數有定義變量的語句時會提早聲明變量,而不賦值,當執行到賦值語句的時候的纔會給與變量賦值。所以上邊代碼等於: Var space =’global’; Function test(){ Var space; Console.log(space); //=>undefined 變量雖有定義可是沒有值 Var space;space=’function’; //變量在這裏賦予初始值,可是變量在函數體內都是有定義的(var space); Console.log(space); //=> function 變量以賦予初始值 } JS函數獨有這個特性叫作 聲明提早。 做爲屬性的變量: 當生命一個全局變量變量時,實際上定義了一個全局對象的屬性,當經過var關鍵字時次屬性是不可配置,不能使用delete刪除此變量。當不嚴格的定義(不實用var)是能夠經過delete刪除。 JS全局變量是全局對象的屬性,局部變量沒定義,可是也能夠想到是函數對象的屬性。 JS 容許使用this來引用全局變量,可是沒方法能夠引用局部變量。 JS做用域鏈: JS是基於詞法做用域的:全局變量在程序中始終有意義,局部變量在函數體內及函數嵌套的函數體內始終有意義。 若是將變量看做一個自定義實現的對象的屬性,那麼換一個角度來解讀變量做用域。每一段代碼都是有一個與之關聯的做用域鏈。這個做用域鏈對應着一個對象的列表或者鏈表。那麼當執行程序的時候,JS會一次查找每一個對象的做用域鏈。當發現此變量的時候就定義此變量,當沒有此變量就拋出一個錯誤。 那麼對於頂層代碼來講(不包含函數定義的語句),就會有一個全局做用域鏈。 對一個不包含嵌套函數的函數做用域鏈上包含兩個對象:參數變量,局部變量的一個對象,和全局變量對象 。 對於嵌套函數來講: 至少有三個對象::參數變量,局部變量的一個對象,和全局變量對象 。 當定義一個函數保存一個做用域鏈,當調用這個函數的時候,會建立一個更長的函數調用的對象加到這個做用域鏈,對於嵌套函數來講更復雜,會從新定義內部函數,並建立一個新的對象加到做用域鏈。因次每次調用外部函數時做用域鏈都是不相同的。
相關文章
相關標籤/搜索