原生JS筆記01:執行環境與作用域鏈 概念 執行環境 作用域

概念

  1. 執行環境(execution context):是JavaScript中一個非常重要的概念。執行環境定義了變量或函數有權訪問的其他數據,決定了它們各自的行爲。

  2. 執行環境的變量對象:每個執行環境都有一個對應的變量對象,它用於存儲環境中定義的所有變量和函數。我們在代碼中無法直接訪問它,但解析器在後臺會實際使用它。

  3. 作用域鏈(scope chain):當函數被執行時,它的執行環境會被推入一個環境棧中。在函數被執行完畢後,會從棧中彈出,將控制權交給棧頂的執行環境,棧底是全局執行環境。當我們查詢標識符的作用時,採用就近原則,從棧頂向棧底查找,這就是作用域鏈。

執行環境

  1. 全局執行環境
    全局執行環境根據宿主的不同,會有變化。
    衆所周知,JavaScript實際上是ECMAScript以Web瀏覽器爲宿主後的稱謂。一個簡單的公式如下:
    JavaScript = ECMAScript + BOM + DOM
    所以,JavaScript的所有全局變量和函數,都是作爲window對象的屬性創建的。
function my_global_func(){
console.log(123)
}
var test_var = 'hello'

console.log(window.test_var) // hello
console.log(window.my_global_func) // ƒ (){console.log(123)}
  1. 局部執行環境
    每個函數都有自己的局部執行環境,生成一個“變量對象”,函數內定義的所有變量和函數,都會作爲“變量對象”的屬性存在。
var color = 'blue'
function changeColor(){
    color = 'red'
}
changeColor()

如上面這段代碼所示,存在一個全局執行環境和一個局部執行環境,該局部執行環境由函數“changeColor”生成。
在此段代碼片段中,函數“changeColor”的局部執行環境中,並沒有定義任何變量,因此該局部執行環境中只有一個默認的變量: arguments。

  1. arguments
    在任何函數中,都存在一個默認的無需定義的變量:arguments,它以數組的形式存儲函數的入參。
    也可以認爲,它是函數執行環境中,“變量對象”的默認屬性,值得注意的是,全局執行環境沒有arguments屬性。
var test = function(){
console.log(arguments)
}
test('1','2') //['1','2']

console.log(arguments) // 報錯

arguments除了包含函數入參,擁有數組的方法以外,還擁有一個callee方法,這個方法的具體用法,後面再講。

作用域

作用域:一個函數/變量可以被使用的作用範圍,被稱爲作用域。
在JAVA、C、C++ 等開發語言當中,變量/函數 的作用域以塊爲單位。但在JavaScript這門語言當中,卻不是以塊爲單位進行作用域的判斷的。

if(true){
    var color = 'blue'
}
console.log(color) // blue

在存在塊級作用域的語言中,以上代碼會報錯,但JavaScript卻能夠打印出在if塊中定義的變量的值。原因在於JavaScript中var關鍵字定義的變量存在“變量”提升這個過程,在編譯的過程中,實際執行過程如下:

var color = undefined
if(true){
     color = 'blue'
}
console.log(color) // blue

而變量提升的本質,是提前給執行環境中的“變量對象”設置屬性值,而局部執行環境已函數爲單位,因此變量提升的過程也只到函數這一層。
那麼,在一個函數內,是否可以訪問其執行環境以外的變量呢?
答案當然是肯定的。

var color = 'blue'
function test(){
  console.log(color)
}
test() // blue

通過上面這個簡單的例子,我們可以發現,在函數的局部執行環境中,可以訪問全局執行環境中的變量。

var color = 'blue'
function test(){
    var color02 = 'red'
    var test02 = function(){
        console.log(color)
        console.log(color02)
    }
    test02()
}
test() // blue  red

通過上面這個例子,我們可以發現,在函數的局部執行環境中,不僅可以訪問全局執行環境的變量,還可以訪問上一層函數中定義的變量。
實際上:在一個函數被執行時,它被推入一個環境棧,最上層永遠是執行中的函數的執行環境,其次爲該函數的上一層函數的執行環境,以此類推,底層爲全局執行環境。
當編譯器尋找標識符時,會從棧頂向棧底依次搜尋,一旦找到符合條件的標識符便結束此次搜尋,如果編譯器未能找到該標識符,便會報錯。

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