1. 程式人生 > >【作用域】變數提升

【作用域】變數提升

一、什麼是變數提升

先思考下面程式碼

console.log(a);
var a = 1;
test();
function test(){
  console.log('test is running')
}

結果是

console.log(a); // undefined
var a = 1;
test(); // test is running
function test(){
  console.log('test is running')
}
b=2;

變數a函式test的定義在使用之後,為什麼沒有報錯呢?原因就是我們常說的變數提升

我們知道ES6之前沒有塊級作用域,只有全域性作用域

函式作用域。JS在執行指令碼之前會先解析程式碼,在解析的時候會建立一個全域性執行上下文,並將其中的變數、函式都先拿出來,並給它們提前在記憶體中開闢好空間,變數暫時賦值為undefined函式則會宣告好,整個儲存在記憶體中,這一步做完了再正式執行程式。函式在執行的時候同理,也會先解析程式碼,建立一個函式執行上下文,將其中的變數、函式提前準備好。

所以,當執行console.log(a)的時候,JS解析器已經提前把a定義好並賦值為undefined。可以在函式定義前就呼叫。

二、變數提升的幾點注意事項

1.不帶var修飾符的變數不會提升
console.log(a); // Uncaught ReferenceError: a is not defined
a = 1;

JS在解析變數時會查詢var關鍵字,如果變數沒有通過var來定義,則不能提前定義。

2.函式名和變數名相同時,函式會覆蓋變數
// 先定義變數再定義函式的時候
console.log(typeof a); // function
var a = 1;
function a(){}

// 先定義函式再定義變數的時候
console.log(typeof b); // function
function b(){}
var b = 2;

不好意思,function有主角光環,不管你變數怎麼調整出場順序,最後的贏家都是function

3.let 和 const不會有變數提升這種現象
console.
log(a); // Uncaught ReferenceError: a is not defined console.log(b); let a = 1; const b = 2;

按照一般的邏輯,變數應該在宣告語句之後才可以使用,為了糾正變數提升這種現象,let和const改變了語法行為,它所宣告的變數一定要在聲明後使用,否則會報錯。