作用域
作用域是JavaScript最重要的概念之一。任何程序設(shè)計(jì)語(yǔ)言都有作用域的概念德崭,簡(jiǎn)單來(lái)說(shuō)福铅,作用域就是變量與函數(shù)的可訪問(wèn)范圍,即作用域控制著變量與函數(shù)的可見(jiàn)性和生命周期狸演。在JavaScript中言蛇,作用域是靠函數(shù)來(lái)形成的,也就是說(shuō)一個(gè)函數(shù)的變量在函數(shù)外不可以訪問(wèn)宵距。
1. 全局作用域
在代碼中任何地方都能訪問(wèn)到的對(duì)象擁有全局作用域腊尚。
- 最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域
var n =2;
function fn(){
var a = 1;
return a;
}
console.log(fn()); // 1
console.log(n); // 2
console.log(a); // 報(bào)錯(cuò)error
- 所有未定義直接賦值的變量自動(dòng)聲明為擁有全局作用域
var n =2;
function fn(){
a = 1;
return a;
}
console.log(fn()); // 1
console.log(n); // 2
console.log(a); // 1
- 所有window對(duì)象的屬性擁有全局作用域
2 .局部作用域
和全局作用域相反,局部作用域一般只在固定的代碼片段內(nèi)可訪問(wèn)到满哪,最常見(jiàn)的例如函數(shù)內(nèi)部婿斥,所以在一些地方會(huì)把這種作用域成為函數(shù)作用域。
var n =2;
function fn(){
var a = 1;
return a;
}
console.log(fn()); // 1
console.log(n); // 2
console.log(a); // 報(bào)錯(cuò)error
上述代碼中a是函數(shù)內(nèi)部聲明并賦值翩瓜,擁有局部作用域受扳,只能帶函數(shù)fn內(nèi)部使用,在fn外部使用就會(huì)報(bào)錯(cuò)兔跌,這就是局部作用域的特性勘高,只能在固定的代碼片段內(nèi)可以使用,外部則無(wú)法訪問(wèn)。
作用域鏈
當(dāng)聲明一個(gè)函數(shù)時(shí)华望,局部作用域一級(jí)一級(jí)向上扣起來(lái)蕊蝗,就是作用域鏈。
1. 當(dāng)執(zhí)行函數(shù)時(shí)赖舟,總是先從函數(shù)內(nèi)部找尋變量蓬戚,即局部作用域開(kāi)始。
2. 如果內(nèi)部找不到(函數(shù)的局部作用域沒(méi)有)宾抓,則會(huì)向創(chuàng)建函數(shù)的作用域(聲明函數(shù)的作用域)尋找子漩,依次向上
看個(gè)例子:
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
時(shí),創(chuàng)建函數(shù)fn1
的執(zhí)行環(huán)境(調(diào)用對(duì)象)石洗,并將該對(duì)象置于鏈表開(kāi)頭幢泼,然后將函數(shù)fn
的調(diào)用對(duì)象放在第二位,最后是全局對(duì)象讲衫,作用域鏈的鏈表的結(jié)構(gòu)是fn1->fn->window(全局)缕棵。從鏈表的開(kāi)頭尋找變量a,即fn1
函數(shù)內(nèi)部找變量a涉兽,找到了招驴,結(jié)果是20。
同樣枷畏,執(zhí)行fn2
時(shí)别厘,作用域鏈的鏈表的結(jié)構(gòu)是fn2->fn->window(全局)。從鏈表的開(kāi)頭尋找變量a矿辽,即fn2
函數(shù)內(nèi)部找變量a丹允,找不到,于是從fn
內(nèi)部找變量a袋倔,找到了雕蔽,結(jié)果是10。
最后在最外層打印出變量a宾娜,直接從變量a的作用域即全局作用域內(nèi)尋找批狐,結(jié)果為1。