如果你不知道什么是作用域局骤,建議你先看什么是作用域鏈,什么是原型鏈暴凑。這篇文章峦甩,因?yàn)檫@些內(nèi)容都是有關(guān)聯(lián)性的。
什么是自由變量现喳?
如我在全局中定義了一個(gè)變量a凯傲,然后我在函數(shù)中使用了這個(gè)a,這個(gè)a就可以稱(chēng)之為自由變量拿穴,可以這樣理解泣洞,凡是跨了自己的作用域的變量都叫自由變量。
vara = "追夢(mèng)子";function b(){
? ? console.log(a); //追夢(mèng)子}
b();
上面的這段代碼中的變量a就是一個(gè)自由變量默色,因?yàn)樵诤瘮?shù)b執(zhí)行到console.log(a)的時(shí)候球凰,發(fā)現(xiàn)在函數(shù)中找不到變量a,于是就往上一層中找腿宰,最后找到了全局變量a呕诉。
作用域的進(jìn)階
在我講作用域鏈的時(shí)候說(shuō)過(guò)如果有一個(gè)全局變量a,以及函數(shù)中也有一個(gè)變量a吃度,那么只會(huì)作用函數(shù)中的那個(gè)變量a甩挫,都是有一種情況就顯得比較復(fù)雜一些,我們一起來(lái)看看這段代碼椿每。
varaa = 22;function a(){
? ? console.log(aa);
}function b(fn){
? ? varaa = 11;
? ? fn();
}
b(a); //22
最后打印的不是11而是22伊者,為什么會(huì)這樣呢英遭?在我解釋之前我建議你事先看一下js中的執(zhí)行上下文,菜鳥(niǎo)入門(mén)基礎(chǔ)亦渗。這一文挖诸,如果不了解js的執(zhí)行順序就比較難以理解,另外如果你看了我這幾天的文章應(yīng)該有種感覺(jué)法精,就是內(nèi)容的關(guān)聯(lián)性都特別強(qiáng)多律,這也是為什么很多js新手朋友不能夠理解的地方。
我們接著說(shuō)為什么打印的是22搂蜓,一起來(lái)分析一下這段代碼狼荞。
假如我們的代碼是這樣的
varaa = 22;function a(){
? ? console.log(aa);
}
打印出的是22,我想大家應(yīng)該沒(méi)有意見(jiàn)帮碰,但是有一點(diǎn)我一定要提相味,那就是在創(chuàng)建這個(gè)函數(shù)的時(shí)候,這個(gè)函數(shù)的作用域就已經(jīng)決定了收毫,而是不是在調(diào)用的時(shí)候攻走,這句話(huà)至管重要。
有了這句話(huà)的基礎(chǔ)是不是理解上面的那段代碼就變得不值一提了此再?
為了照護(hù)新手朋友我還是分析一下過(guò)程吧昔搂。
首先我們創(chuàng)建了一個(gè)全局變量aa
varaa = 22;
接著我們創(chuàng)建了一個(gè)函數(shù)a
function a(){
? ? console.log(aa);
}
這時(shí)js解析這個(gè)函數(shù)的時(shí)候,就已經(jīng)決定了這個(gè)函數(shù)a的作用域输拇,既如果在函數(shù)a中找不到變量aa那就會(huì)到全局變量中找摘符,如果找到了就返回這個(gè)aa,如果找不到就報(bào)錯(cuò)策吠。
接著我們又創(chuàng)建了一個(gè)函數(shù)b
function b(fn){
? ? varaa = 11;
? ? fn();
}
在函數(shù)b中我們定義了又重新定義了這個(gè)變量aa逛裤,雖然我們這個(gè)時(shí)候重新定義了變量aa,但是因?yàn)楹瘮?shù)a的作用域在創(chuàng)建的時(shí)候已經(jīng)決定了猴抹,所以在函數(shù)b中創(chuàng)建的那個(gè)變量aa以及和函數(shù)a里面的那個(gè)變量aa沒(méi)有關(guān)系了带族。
function b(fn){
? ? varaa = 11;
? ? fn();
}
b(a);
我們把函數(shù)a傳到了函數(shù)b中,并且當(dāng)做函數(shù)b的形參蟀给,接著我們執(zhí)行了這個(gè)被傳進(jìn)去的函數(shù)a蝙砌,最后打印出來(lái)的就是22。
在創(chuàng)建這個(gè)函數(shù)的時(shí)候跋理,這個(gè)函數(shù)的作用域就已經(jīng)決定了择克,而是不是在調(diào)用的時(shí)候。