JS 中作用域的概念:
表示變量或函數(shù)起作用的區(qū)域,指代了它們?cè)谑裁礃拥纳舷挛闹袌?zhí)行,亦即上下文執(zhí)行環(huán)境。Javascript 的作用域只有兩種:全局作用域和本地作用域,本地作用域是按照函數(shù)來(lái)區(qū)分的。
首先來(lái)看幾道題目:
1.
if(true){
var aa= "bb";
}
console.log(aa); //bb
for(var i = 0; i <100; i++){
//do
}
console.log(i); //100
2.
var bb = '11111';
function aa() {
alert(bb);//undefine
var bb = 'test';
alert(bb);//test
var cc = "test1";
alert(age);// 語(yǔ)法錯(cuò)誤
}
aa();
3.
var test = '1111111';
function aa() {
alert(test);
}
function bb() {
var test = '22222222';
aa();
}
bb();//alert(1111111);
4.
alert(typeof aa); //function
alert(typeof bb); //undefined function aa() { // 函數(shù)定義式
alert('I am 111111111');
};
var bb = function() { // 函數(shù)表達(dá)式
}
alert(typeof bb);//function
5.
function aa(){
var bb = "test";
cc = "測(cè)試";
alert(bb);
}
aa();
alert(cc);// 測(cè)試
alert(bb);// 語(yǔ)法報(bào)錯(cuò)
上面這 5 道題目全部概括了 js 中作用域的問(wèn)題。
可以總結(jié)出這么幾個(gè)觀點(diǎn):
從第一題中可以看出來(lái),在{}中執(zhí)行后,變量并沒(méi)有被銷(xiāo)毀,還是保存在內(nèi)存中的,因此我們可以訪問(wèn)到的。
這里提到函數(shù)的作用域鏈這個(gè)概念,在 ECMA262 中,是這樣的
任何執(zhí)行上下文時(shí)刻的作用域,都是由作用域鏈 (scope chain) 來(lái)實(shí)現(xiàn)。 在一個(gè)函數(shù)被定義的時(shí)候,會(huì)將它定義時(shí)候的 scope chain 鏈接到這個(gè)函數(shù)對(duì)象的[[scope]]屬性。 在一個(gè)函數(shù)對(duì)象被調(diào)用的時(shí)候,會(huì)創(chuàng)建一個(gè)活動(dòng)對(duì)象 (也就是一個(gè)對(duì)象,然后對(duì)于每一個(gè)函數(shù)的形參,都命名為該活動(dòng)對(duì)象的命名屬性,然后將這個(gè)活動(dòng)對(duì)象做為此時(shí)的作用域鏈 (scope chain) 最前端, 并將這個(gè)函數(shù)對(duì)象的 [[scope]] 加入到 scope chain 中。 所以題目 3 結(jié)果是 alert(1111111);
如題目 4 開(kāi)始 alert(bb); //undefine ,alert(age)//語(yǔ)法報(bào)錯(cuò),這兩個(gè)有什么區(qū)別呢,原因就是后面有 var bb =“test”,在初始化的時(shí)候提前處理了 var 這個(gè)關(guān)鍵字,只是這個(gè)開(kāi)始未賦值
將代碼修改成這樣的,可以看出來(lái)
var dd = '11111';
function aa() {
alert(bb);//undefine
var bb = 'test';
alert(bb);//test
var cc = "test1";
alert(age);// 語(yǔ)法錯(cuò)誤
}
aa();
alert(dd);//11111
alert(cc);// 語(yǔ)法報(bào)錯(cuò)
此處 alert(bb)沒(méi)有報(bào)語(yǔ)法錯(cuò)誤,alert(age)報(bào)語(yǔ)法錯(cuò)誤。
但是請(qǐng)注意:
<script>
alert(typeof aa); // 結(jié)果: undefined
</script>
<script>
function aa() {
alert('yupeng');
}
</script>
這說(shuō)明 js 預(yù)編譯是以段為單元的。題目 4 同理
函數(shù)里面的定義的變量,在函數(shù)執(zhí)行完后就銷(xiāo)毀了,不占有內(nèi)存區(qū)域了。
所以題目 2 最后的 alert(cc);語(yǔ)法報(bào)錯(cuò),題目 5 最后到 alert(bb)同理。