1. 全局變量與局部變量
全局變量:定義在函數(shù)外部的變量可以被叫做全局變量
局部變量:定義在函數(shù)內(nèi)部的變量臀突,但是如果變量在函數(shù)內(nèi)部沒有使用var來聲明缰犁,那么該變量也會(huì)被認(rèn)為是全局變量达舒。
1唬复,全局變量對(duì)應(yīng)的作用域是整個(gè)代碼穗椅,即在代碼的任何部分都是可以調(diào)用該變量的
2下梢,局部變量對(duì)應(yīng)的作用域是函數(shù)內(nèi)部客蹋,只能在函數(shù)內(nèi)部使用,如果在函數(shù)外部使用就會(huì)出錯(cuò)
3孽江,局部變量的優(yōu)先級(jí)大于全局變量讶坯,即如果全局變量和局部變量名字一樣,那么在函數(shù)內(nèi)部局部變量會(huì)覆蓋掉全局變量岗屏。
2. 作用域鏈(scope chain)
全局作用域和局部作用域中變量的訪問權(quán)限辆琅,其實(shí)是由作用域鏈決定的钧舌。
每次進(jìn)入一個(gè)新的執(zhí)行環(huán)境,都會(huì)創(chuàng)建一個(gè)用于搜索變量和函數(shù)的作用域鏈涎跨。作用域鏈?zhǔn)呛瘮?shù)被創(chuàng)建的作用域中對(duì)象的集合洼冻。作用域鏈可以保證對(duì)執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。
作用域鏈的最前端始終是當(dāng)前執(zhí)行的代碼所在環(huán)境的變量對(duì)象(如果該環(huán)境是函數(shù)隅很,則將其活動(dòng)對(duì)象作為變量對(duì)象)撞牢,下一個(gè)變量對(duì)象來自包含環(huán)境(包含當(dāng)前還行環(huán)境的環(huán)境),下一個(gè)變量對(duì)象來自包含環(huán)境的包含環(huán)境叔营,依次往上屋彪,直到全局執(zhí)行環(huán)境的變量對(duì)象。全局執(zhí)行環(huán)境的變量對(duì)象始終是作用域鏈中的最后一個(gè)對(duì)象绒尊。
標(biāo)識(shí)符解析是沿著作用域一級(jí)一級(jí)的向上搜索標(biāo)識(shí)符的過程畜挥。搜索過程始終是從作用域的前端逐地向后回溯,直到找到標(biāo)識(shí)符(找不到婴谱,就會(huì)導(dǎo)致錯(cuò)誤發(fā)生)蟹但。
從下面一個(gè)例子來看
var a = 1
function fn1(){
function fn2(){
console.log(a);
}
var a = 4;
fn2();
}
fn1() //輸出多少
根據(jù)上方作用域鏈的概念可以知道,fn2中并沒有定義a谭羔,那么就會(huì)向上一級(jí)作用域尋找华糖,這里的上一級(jí)作用域具體指的是函數(shù)聲明的作用域,在上一級(jí)作用域中瘟裸,變量a=4客叉,因此最后輸出為4
再看另外一個(gè)例子
var a = 1
function fn1(){
function fn2(){
console.log(a);
}
fn2();
var a = 4
}
fn1() //輸出多少
和上一個(gè)例子稍有不同的是,在fn1內(nèi)部先執(zhí)行了fn2话告,再聲明a=4兼搏,而這一次并沒有和上一個(gè)例子一樣輸出4,而是會(huì)輸出undefined沙郭。這是因?yàn)樵诤瘮?shù)內(nèi)部的作用域下佛呻,同樣會(huì)適用變量提升的概念。fn1的內(nèi)部相當(dāng)于
function fn2(){
console.log(a);
}
var a;
fn2();
a = 4;
這樣不難看出棠绘,結(jié)果會(huì)輸出undefined.
總結(jié)
- 函數(shù)在執(zhí)行的過程中件相,先從自己內(nèi)部找變量
- 如果找不到,再?gòu)膭?chuàng)建當(dāng)前函數(shù)所在的作用域去找, 以此往上
- 注意找的是變量的當(dāng)前的狀態(tài)(適用變量提升)