從別人給我的一道題目說起饥漫,請(qǐng)問執(zhí)行下面語句后的輸出結(jié)果
var a = 3;
function test(){
console.log(a);
a(4);
function a(b){
a = b;
}
console.log(a);
}
console.log(a);
test();
我最初的答案是:
3
3
4
其實(shí)應(yīng)該是
3
function a(b)
4
這道題包含了了函數(shù)提升與變量優(yōu)先級(jí)的問題幅聘。為了更好地理解這個(gè)復(fù)合問題震糖,我們一個(gè)一個(gè)說起总珠。
變量提升#
意思是你代碼中聲明變量的所在行肋杖,其實(shí)并不是真正聲明的地方溉仑,javascript編譯時(shí)會(huì)統(tǒng)一將聲明提升到作用域的最上方。
比如當(dāng)你寫下這行代碼時(shí):
var a = 3;
編譯器會(huì)將變量聲明提升到代碼頂部状植,但是賦值仍然在原來的地方浊竟,變?yōu)椋?/p>
var a;
a = 3;
舉個(gè)例子:
var a = 3 ;
console.log(a);
console.log(b);
var b = 2 ;
其輸出結(jié)果為:
3
undefined
因?yàn)槠鋵?shí)際編譯代碼為
var a,b;
a = 3;
console.log(a);
console.log(b);
b = 2;
那現(xiàn)在問題升級(jí)一下,引入作用域的概念
var a = 3;
function test(){
console.log(a);
a = 4;
console.log(a);
}
其結(jié)果為:
3
4
恩津畸,我不知道有沒有迷惑到你振定,反正我被我自己迷惑到了,我們?cè)賮硐乱活}
var a = 3;
function test(){
console.log(a);
var a = 4;
console.log(a);
}
test();
其結(jié)果為:
undefined
4
這里要先說一下同名變量優(yōu)先級(jí)洼畅,在同一作用域內(nèi)吩案,兩個(gè)同名變量中,局部變量的優(yōu)先級(jí) > 全局變量的優(yōu)先級(jí)帝簇,即test方法中的a會(huì)覆蓋外部的a徘郭。
再回到變量提升,所以test方法在編譯后實(shí)際是這樣的
function test(){
var a ; // 變量聲明提升到方法頂部
console.log(a);
a = 4; // 賦值仍然在原處進(jìn)行
console.log(a);
}
變量作用域#
所有不用var聲明的變量都是全局變量
在函數(shù)體內(nèi)丧肴,同名的局部變量或參數(shù)優(yōu)先級(jí)會(huì)高于同名局部變量残揉,即
var a = 3;
function test() {
var a = 4;
console.log(a);
}
test();
console.log(a);
會(huì)輸出
4
3
函數(shù)提升#
變量提升理解了,函數(shù)提升會(huì)好理解一些芋浮,函數(shù)的聲明會(huì)提到作用域的頂端稳吮,但不同的是沪么,函數(shù)提升會(huì)將其方法體的內(nèi)容一起提升,舉例來說
function test(){
test1();
var b = 5;
function test1(){
console.log(b);
}
}
test();
會(huì)被編譯為
function test(){
var b;
function test1(){
console.log(b);
}
test1();
b = 5;
}
test();
輸出
undefined
函數(shù)聲明方式分為兩種,函數(shù)聲明(函數(shù)式聲明)和函數(shù)表達(dá)式(變量式聲明)砌创,<b>只有函數(shù)聲明才會(huì)執(zhí)行函數(shù)提升</b>
console.log(a);
console.log(b);
// 函數(shù)聲明 執(zhí)行函數(shù)提升
function a(){}
// 函數(shù)表達(dá)式 不執(zhí)行函數(shù)提升 但可以看成是變量提升
var b = function(){}
輸出
function a()
undefined
最后,再看下這個(gè)問題
var a;
function a(){
console.log(2);
}
console.log(a);
結(jié)果到底會(huì)是undefined還是function烟很?輸出如下
function a()
那再加強(qiáng)一下
var a;
function a(){
console.log(2);
}
console.log(a);
a();
a = 3;
console.log(a);
輸出
function a()
2
3
函數(shù)提升優(yōu)先級(jí)比變量提升要高谴垫,且不會(huì)被變量聲明覆蓋,但是會(huì)被變量賦值覆蓋〈嬲埽現(xiàn)在應(yīng)該明白最上方那道題為什么會(huì)是這個(gè)結(jié)果了吧因宇?其編譯過程如下:
var a;
function test() {
function a(b) {
a = b;
}
console.log(a); // functing a(b)
a(4);
console.log(a); // 4
}
a = 3;
console.log(a); // 3
test();