什麼是作用域
作用域指的是變量存在的範圍。
- 在 JavaScript 中, 對象和函數同樣也是變量,可以了解作用域為可通路變量,對象,函數的集合
在 的規範中,
ES5
JavaScript
隻有兩種作用域:一種是全局作用域,變量在整個程式中一直存在,所有地方都可以讀取;
另一種是函數作用域,變量隻在函數内部存在。
又新增了塊級作用域
ES6
全局作用域
所有頂層函數聲明或者大括号之外定義的變量,都在全局作用域裡。
function fxFn () {
fxs = 2
}
var fx = 1
console.log(window.fx) // 1
// console.log(fxs) 未定義
fxFn() // 執行後fxs成為全局變量
console.log(fxs) // 2
var聲明的變量與不使用var聲明的變量差別
局部作用域(函數作用域與塊級作用域)
函數作用域
在
JavaScript
中,任何定義在函數體内的變量或者函數都将處于函數作用域中,這些變量通常無法被在函數外部使用
- 局部變量在函數開始執行時建立,函數執行完後局部變量會自動銷毀。
- 當函數體内局部變量和函數體外的變量重名的話,内部局部變量将會遮蓋同名的全局變量
var fx = 'fx is a good girl'
function fxFn () {
console.log(fx)
var fx = 'fx is a great girl'
console.log(fx)
fx = 'very good'
console.log(fx)
}
console.log(fx)
fxFn()
console.log(fx)
// 依次輸出 1. fx is a good girl 2. undefined 3. fx is a great girl 4. very good 5.fx is a good girl
var fx = 'fx is a girl'
var fxs = 'yes'
function fxFn () {
console.log(fx) // undefined
console.log(fxs) // yes
fx = 'very good'
fxs = 'not'
console.log(fx) // very good
console.log(fxs) // not
var fx = 'fx is a great girl'
console.log(fx) // fx is a great girl
console.log(fxs) // not
}
console.log(fx) // fx is a girl
console.log(fxs) // yes
fxFn()
console.log(fx) // fx is a girl
console.log(fxs) // not
什麼是作用域嵌套
當一個塊或函數嵌套在另一個塊或函數中時,就發生了作用域的嵌套。是以,在目前作用域中無法找到某個變量時,引擎就會在外層嵌套的作用域中繼續查找,直到找到該變量,或抵達最外層的作用域(也就是全局作用域)為止。
示例
如下代碼,對
b
進行的
RHS
引用無法在函數
foo
内部完成,但可以在上一級作用域(在這個例子中就 是全局作用域)中完成。
function foo (a) {
console.log(a + b);
}
var b = 2;
foo(2);
函數被調用之前作用域鍊已經存在
fxAge = 'fx is 18 years old'
function fxFn () {
console.log(fxAge) // undefined
var fxAge = 'fx is 8 years old'
var fxSub = 'fx is 25 years old'
console.log(fxAge) // fx is 8 years old
function fxFnSub () {
console.log(fxSub) // fx is 25 years old
console.log(fxAge) // fx is 8 years old
}
return fxFnSub;
}
var fx = fxFn()
fx()
如下代碼,在函數被執行之前已經建立了兩條作用域鍊:
- 全局作用域 ->
函數作用域fxFn
- 全局作用域 ->
函數作用域fxFnSub
var fx = 'fx is a great girl'
function fxFn () {
// 輸出的是全局作用域的 fx:fx is a great girl
console.log(fx)
}
function fxFnSub () {
var fx = 'fx is 18 years old'
return fxFn
}
var myFx = fxFnSub()
myFx()
// x 的作用域是全局作用域,全局作用域中沒有對 a 進行定義
var x = function () {
console.log(a);
};
function y(f) {
var a = 2;
f();
}
y(x) // ReferenceError: a is not defined
綜上示例,可以了解為
函數的作用域與變量一樣,就是其聲明時所在的作用域,與其運作時所在的作用域無關。
周遊嵌套作用域鍊規則
引擎從目前的執行作用域開始查找變量,如果找不到, 就向上一級繼續查找。當抵達最外層的全局作用域時,無論找到還是沒找到,查找過程都會停止。
作用域鍊
如圖所示,這個建築代表程式中的嵌套作用域鍊。第一層樓代表目前的執行作用域,也就是你所處的位置。建築的頂層代表全局作用域。