原文連接:dmitripavlutin.com/variables-l…javascript
通常的,***變量聲明var***和***函數聲明function fun() {...}***,都會發生變量提高,即把變量和函數的定義移到做用域的頂部。java
可是let不會被提高,(有提高,可是無效,在定義以前不能使用)函數
console.log(num); // => nudefined
var num;
num = 10;
console.log(num); // => 10
複製代碼
變量在聲明以前被訪問,會被認定爲undefined。ui
console.log(fun); // => function fun() {....}
fun(); // => 123
function fun(){
return 123;
}
複製代碼
函數在聲明以前被調用,能夠執行,由於末尾定義的函數被提高到做用域頂部了。spa
console.log(fun()); //fun is not a function
var fun = function() {
return 123;
};
複製代碼
上面的這種屬於變量的聲明,fun在聲明以前被訪問了。code
當引擎訪問變量的時候,生命週期包括如下幾個階段:cdn
經過聲明階段可是沒有達到初始化階段的變量處於未定義狀態。blog
經過初始化階段可是沒有達到賦值階段的變量處於undefined狀態。生命週期
引擎處理var的過程ip
javascript引擎遇到做用域裏面的全部***var***聲明的變量或函數。都會讓她們在其餘任何語句執行以前,經過變量的***聲明階段和初始化階段(初始化undefined)***。
在賦值語句(賦值階段)以前,這些變量的值都爲undefined而且均可以訪問。
嚴格來講,提高的概念是在函數做用域的頂部聲明和初始化變量。而且在聲明階段和初始化階段之間是沒有間隙的。
引擎處理function fun() {...}的過程
javascript引擎遇到做用域裏面全部的***function fun() {...}聲明的函數,都會讓它們在其餘語句執行以前經過***聲明,初始化,賦值階段。
三個階段之間是沒有間隙的。
let變量的處理方式和var不一樣,最主要的區別就是聲明階段和初始化階段被分開了
console.log(num) // => Throws ReferenceError
let num;
console.log(num) // => nudefined
num = 5;
console.log(num) // => 5
複製代碼
const和class類型和let有相同的生命週期,只是const和class只能賦值一次。