
前言
把他們兩個(gè)概念放在一起說(shuō),并不是因?yàn)樗麄冇卸啻箨P(guān)聯(lián),只是因?yàn)樗麄兌紩?huì)被“提前”。
函數(shù)提升
函數(shù)提升,比較好理解,基本就是js的運(yùn)行規(guī)則了,記住就好。就是無(wú)論函數(shù)被定義在上下問(wèn)那個(gè)位置,都會(huì)在代碼執(zhí)行前優(yōu)先定義。比如下面的例子:
fn();
function fn() {
console.log('issac');
}

上面的例子是可以執(zhí)行的,不會(huì)報(bào)錯(cuò),會(huì)正常輸出“issac”。雖然上面說(shuō)到上下文的任何位置,但是這個(gè)任何位置是指同一個(gè)執(zhí)行環(huán)境,怎么才叫同一個(gè)執(zhí)行環(huán)境?比如說(shuō)下面的例子就會(huì)報(bào)錯(cuò):
fn();
function fnCreat(){
function fn(){
console.log('issac');
}
}
fnCreate();
為什么會(huì)報(bào)錯(cuò)?fn函數(shù)執(zhí)行的執(zhí)行環(huán)境,和fn定義的執(zhí)行環(huán)境已經(jīng)不同,每個(gè)函數(shù)都創(chuàng)建一個(gè)執(zhí)行環(huán)境,自身的執(zhí)行環(huán)境,外部環(huán)境對(duì)其是不可見(jiàn)的,全局執(zhí)行環(huán)境對(duì)于任何一個(gè)函數(shù)的函數(shù)體內(nèi)的代碼來(lái)說(shuō)都是外部執(zhí)行環(huán)境。

所以上面你在全局執(zhí)行環(huán)境調(diào)用,就要在全局執(zhí)行環(huán)境定義。
PS:談到函數(shù)定義想必會(huì)想到下面這樣的方式定義函數(shù),這樣的定義函數(shù)個(gè)人覺(jué)得是很好看的:
fn();
var fn = function() {
console.log('issax');
}
這種函數(shù)的定義方式叫“函數(shù)表達(dá)式”,這樣定義函數(shù)是不會(huì)被函數(shù)提升,因此上面的代碼執(zhí)行會(huì)拋出異常:

變量的聲明提前
變量和函數(shù)有一點(diǎn)相同:他們都會(huì)被提前到當(dāng)前作用域的頂部;但是變量的提前和函數(shù)的提前也是有一點(diǎn)不同:函數(shù)是會(huì)被提升,并且會(huì)定義,而變量的提前是不會(huì)被提前定義的,即不會(huì)當(dāng)前作用域提前定義;如果你不清楚作用域的話,對(duì)于函數(shù)來(lái)說(shuō),你可以籠統(tǒng)地認(rèn)為是函數(shù)體內(nèi)部。
function fn(){
console.log(a);
var a = 2;
}
fn();

如上面的例子所見(jiàn),a變量沒(méi)有被提前定義。
如果不會(huì)被提前定義,那么怎么體現(xiàn)變量的聲明提前?
你知道作用域鏈(感興趣可以自行Google)嗎?不知道?也不要緊,寫(xiě)過(guò)js代碼的coder,都應(yīng)該會(huì)有這樣的經(jīng)驗(yàn):函數(shù)內(nèi)部可以訪問(wèn)到外層作用域(比如說(shuō)最外層的全局作用域)定義的變量和函數(shù),而函數(shù)內(nèi)部的定義的和外層作用域同名的變量會(huì)遮蓋外層的,就是說(shuō)如果函數(shù)內(nèi)部有和外層同名的函數(shù)會(huì)變量,內(nèi)部的優(yōu)先級(jí)更高,了解到這一點(diǎn)就算不了解作用域鏈也可以理解變量提升。
var a = 1;
function fn() {
var a = 2;
console.log(a);
}
fn();

變量的聲明提前就體現(xiàn)在下面這個(gè)例子:
var a = 1;
function fn() {
console.log(a);
var a = 2;
console.log(a);
}
fn();
你認(rèn)為會(huì)輸出什么?會(huì)輸出 1 2 ?然而并不是!

為什么會(huì)這樣,就是因?yàn)樽兞康穆暶魈崆?,相信到這里你已經(jīng)大概知道什么是變量提前,通俗地講:在當(dāng)前作用域內(nèi),變量會(huì)提前聲明,遮蓋外層作用域的同名變量,因?yàn)闆](méi)有解析作用域鏈,所以就籠統(tǒng)地說(shuō)一下,畢竟在深入學(xué)習(xí)前就得不求甚解嘛。