作用域
作用域是JavaScript最重要的概念之一夺溢。任何程序設(shè)計語言都有作用域的概念登澜,簡單來說淹辞,作用域就是變量與函數(shù)的可訪問范圍床未,即作用域控制著變量與函數(shù)的可見性和生命周期竭翠。在JavaScript中,作用域是靠函數(shù)來形成的薇搁,也就是說一個函數(shù)的變量在函數(shù)外不可以訪問斋扰。
1. 全局作用域
在代碼中任何地方都能訪問到的對象擁有全局作用域。
1.最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域
var n =2;
function fn(){
var a = 1;
return a;
}
console.log(fn()); // 1
console.log(n); // 2
console.log(a); // 報錯error
2.所有未定義直接賦值的變量自動聲明為擁有全局作用域
var n =2;
function fn(){
a = 1;
return a;
}
console.log(fn()); // 1
console.log(n); // 2
console.log(a); // 1
3.所有window對象的屬性擁有全局作用域
2 .局部作用域
和全局作用域相反,局部作用域一般只在固定的代碼片段內(nèi)可訪問到传货,最常見的例如函數(shù)內(nèi)部屎鳍,所以在一些地方會把這種作用域成為函數(shù)作用域。
var n =2;
function fn(){
var a = 1;
return a;
}
console.log(fn()); // 1
console.log(n); // 2
console.log(a); // 報錯error
上述代碼中a是函數(shù)內(nèi)部聲明并賦值问裕,擁有局部作用域逮壁,只能帶函數(shù)fn內(nèi)部使用,在fn外部使用就會報錯粮宛,這就是局部作用域的特性窥淆,只能在固定的代碼片段內(nèi)可以使用,外部則無法訪問窟勃。
作用域鏈
當(dāng)聲明一個函數(shù)時祖乳,局部作用域一級一級向上扣起來,就是作用域鏈秉氧。
當(dāng)執(zhí)行函數(shù)時眷昆,總是先從函數(shù)內(nèi)部找尋變量,即局部作用域開始汁咏。
如果內(nèi)部找不到(函數(shù)的局部作用域沒有)亚斋,則會向創(chuàng)建函數(shù)的作用域(聲明函數(shù)的作用域)尋找,依次向上
看個例子:
var a = 1;
function fn(){
var a = 10;
function fn1(){
var a = 20;
console.log(a); //20
}
function fn2(){
console.log(a); //10
}
fn1();
fn2();
}
fn();
console.log(a); //1
當(dāng)執(zhí)行fn1時攘滩,創(chuàng)建函數(shù)fn1的執(zhí)行環(huán)境(調(diào)用對象)帅刊,并將該對象置于鏈表開頭,然后將函數(shù)fn的調(diào)用對象放在第二位漂问,最后是全局對象赖瞒,作用域鏈的鏈表的結(jié)構(gòu)是fn1->fn->window(全局)。從鏈表的開頭尋找變量a蚤假,即fn1函數(shù)內(nèi)部找變量a栏饮,找到了,結(jié)果是20磷仰。
同樣袍嬉,執(zhí)行fn2時,作用域鏈的鏈表的結(jié)構(gòu)是fn2->fn->window(全局)灶平。從鏈表的開頭尋找變量a伺通,即fn2函數(shù)內(nèi)部找變量a,找不到逢享,于是從fn內(nèi)部找變量a罐监,找到了,結(jié)果是10瞒爬。
最后在最外層打印出變量a笑诅,直接從變量a的作用域即全局作用域內(nèi)尋找调缨,結(jié)果為1。