作用域
一個(gè)思考題
- 點(diǎn)擊生成的標(biāo)簽a的時(shí)候提示的是什么?
let i, a
for (i = 0; i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br/>'
a.addEventListener('click', function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}
帶著這個(gè)問題我們來看一下作用域和自由變量。
作用域
一張圖帶你認(rèn)知作用域。

作用域.png
- a 可以在紅色框任意地方使用,a1可以在藍(lán)框任意地方使用,a2可以再黃框任意地方使用,a3可以再黑框任意地方使用。
- 如果翻過來,在紅框內(nèi),黑框外使用a3就會(huì)報(bào)錯(cuò)。
所以就會(huì)得到變量對(duì)應(yīng)的使用范圍,這個(gè)范圍就叫做作用域。
作用域有哪些?
- 全局作用域
上述例子中 變量a就是全局作用域,在任意地方都可以使用。 - 函數(shù)作用域
函數(shù)作用就是只能在當(dāng)前函數(shù)中使用,例如a1只能在fn1中使用,超出就不能使用。 - 塊級(jí)作用域
塊級(jí)作用域只能在當(dāng)前的塊中使用,超出當(dāng)前塊就會(huì)報(bào)錯(cuò),例如以下例子。
if (true) {
let x = 100
}
console.log(x) // x is not defined
使用var聲明遍歷會(huì)造成變量提升,所以建議在寫代碼時(shí)盡量使用let,const
關(guān)于var的變量提升,如果剛才塊級(jí)作用域簡單修改一下,打印的值就不一樣,原因就是因?yàn)榘崖暶鱝提升到了最頂部,之后賦值。
if (true) {
var x = 100
}
console.log(x) // 100
變量提升后,這樣看的話就會(huì)一目了然。
var a
if (true) {
x = 100
}
console.log(x) // 100
自由變量
- 一個(gè)變量在當(dāng)前作用域沒有定義,但是他被使用了 。
- 他會(huì)向上級(jí)作用域進(jìn)行尋找,一層一層逐漸往上,直到找到為止。
-
如果全局作用域都沒有找到,就會(huì)提示XX is not defined。
作用域.png
還是這個(gè)圖,使用a2是就向上層找,找到了a2,a1在上上層找到了,a在全局作用域找到。那么這些變量就叫做自由變量。
回到剛開始的問題,實(shí)踐的答案就是每次點(diǎn)擊都是10,那么如何解決這個(gè)問題,只需要把變量i的定義改變?yōu)閴K級(jí)作用域就可以解決。
let a
for (let i = 0; i < 10; i++) {
a = document.createElement('a')
a.innerHTML = i + '<br/>'
a.addEventListener('click', function (e) {
e.preventDefault()
alert(i)
})
document.body.appendChild(a)
}