面試官:聊聊作用域問(wèn)題

全局作用域
script 標(biāo)簽所在的區(qū)域就是所謂的全局作用域,全局作用域有一個(gè)全局的對(duì)象 window
我們所有定義的變量,函數(shù),類,對(duì)象等等都是作用域 window 對(duì)象身上的
var a = 1
// 就是在window 對(duì)象上加上一個(gè) a 屬性
局部作用域(特指函數(shù)作用域)
function foo(a) {
console.log(a)
}
foo(2)
會(huì)產(chǎn)生一個(gè)局部作用域,暫且叫做 fooScope, 這個(gè)作用域里面存儲(chǔ)著這個(gè)局部作用域里面的所有變量定義,函數(shù)定義,對(duì)象定義等等。值得注意的是,全局作用域 globalScope 總是被我們忽視了,局部作用域是可以訪問(wèn)全局作用域的。
所以
globalScope(頂層)
|
|
fooScope(當(dāng)前)
發(fā)出疑問(wèn)
既然局部作用域能夠訪問(wèn)全局作用域的變量,那么局部作用域能不能修改全局作用域變量的值呢?
答案是可以的,我們來(lái)看個(gè)簡(jiǎn)單的例子
var a = 1
function foo() {
a = a + 1
console.log(a); // 2
}
foo()
console.log(a) // 2
函數(shù)參數(shù)是值引用
var a = 1
function foo(a) {
a = a + 1
console.log(a)
}
foo(a) // 2
console.log(a) // 1 說(shuō)明全局中的 a 與函數(shù)參數(shù)的 a 存儲(chǔ)的地方不一樣
嵌套作用域
var a = 1
function foo(a) {
function bar(a) {
console.log("bar ===>", a)
console.log(this)
}
console.log("foo", this)
bar(a)
}
foo(a)
打印出來(lái)的順序如下:
foo: window
bar===> 1
window
先來(lái)說(shuō)說(shuō)這個(gè) a 的尋找過(guò)程:
bar 執(zhí)行,會(huì)在自己的作用域 barScope 找這個(gè)變量 a 發(fā)現(xiàn)找不到,會(huì)在 fooScope 作用域找,發(fā)現(xiàn)找不到 就找到全局作用域 window 中,發(fā)現(xiàn)有 a 這個(gè)變量
我們來(lái)驗(yàn)證下尋找的過(guò)程:
var a = 1
function foo() {
var a = 2
function bar() {
console.log("bar ===>", a)
console.log(this)
}
console.log("foo", this)
bar()
}
foo()
打印出來(lái)如下:
foo:window
bar===>2
bar:window
所以找到要用到的變量之后,就會(huì)停止尋找了。
執(zhí)行順序
詞法解析
解析全局作用域,函數(shù),變量
語(yǔ)法解析
生成程序結(jié)構(gòu)樹
代碼生成
執(zhí)行代碼
var a = 1
function foo() {
var a = 2
function bar(a) {
console.log("bar ===>", a)
console.log("bar ===>",this)
}
console.log("foo", this)
bar(a)
}
foo()
所以
解析階段
全局作用域 有變量 a foo 作用域 有 fooScope.a/window.a bar 作用域 有barScope/fooScope.a/window.a
執(zhí)行階段
bar 執(zhí)行返回,銷毀 foo 執(zhí)行返回,銷毀 window
這樣就形成了作用域鏈
評(píng)論
圖片
表情
