作用域:變量可以被訪問、修改的區域
作用域鏈工作原理:如果一個變量或者其它表達式不在當前的作用域,那麼 Javascript機制會汕頭作用域鏈向上查找直到全局作用域(global或瀏覽器中的window)如果找不到將不可被使用。作用域也可以根據代碼層次分層,以便子作用域可以訪問父作用域,通常是指沿着鏈式作用域鏈查找,而不能從父作用域引用子作用域中的變量和引用。
作用域鏈是什麼:任何一個作用域鏈都是一個堆棧,首先把全局作用域壓入棧底,再按照函數的嵌套關係依次壓入堆棧。在執行的時候就按照這個作用域鏈尋找變量。
JS作用域分類:全局作用域、函數作用域、塊級作用域、動態作用域
全局作用域-blobal/window:
目的:程序的任何地方都可以訪問此變量
定義位置:函數或代碼塊{}外定義
注意:用var定義的變量和不用var聲明的變量,都具有全局作用域,區別是前者是全局變量,後者是作爲全局對象window(宿主爲瀏覽器)的屬性存在。全局變量不可以刪除,全局對象上的屬性可以刪除。另外,在函數內部沒有使用var定義的變量,不具備函數作用域,具備全局作用域,也是全局對象window的屬性,可以進行刪除操作。
函數作用域-function:
定義位置:在函數內部定義的變量,擁有函數作用域,或稱局部作用域。函數作用域內,對外是封閉的,從外層作用域無法直接訪問函數內部的作用域。
如果想讀取函數內部的變量,必須藉助閉包或return的方式。
塊級作用域-{}:
ES6 之前只有全局作用域和函數作用域
ES6 let 和 const
動態作用域-this:
定義:將函數動態綁定在一個對象上,此時this指向該對象,這樣會導致同一個函數會有不同的執行結果。
window.a = 3
function test() {
console.log(this.a)
}
test.bind({a: 2})() //2 此處bind把作用域的範圍進行了修改,指向了{a: 2}
test() //3
靜態作用域和動態作用域
變量的作用域是在定義時決定而不是在執行時決定,也就是說記法作用域取決於源碼,通過靜態分析就能確定,因此詞法作用域也叫靜態作用域。
只能在執行階段才能決定變量的作用域,那就是動態作用域。