js和其他語言一樣,都要經歷編譯和執行階段。
而js在編譯階段的時候,會搜集所有的變量聲明並且提前聲明變量,而其他的語句都不會改變他們的順序,因此,在編譯階段的時候,第一步就已經執行了,而第二步則是在執行階段執行到該語句的時候才執行。
1. 變量提升
console.log(variable); var variable = 'hello'; console.log(variable); // 編譯后 var variable // 變量提升,全局作用域范圍內,此時只是聲明,並沒有賦值 console.log(variable); // undefined variable = '我是全局中的變量'; // 賦值位置不變 console.log(variable); // hello
2.函數提升
必須是函數聲明的形式,不能是函數表達式的形式(函數表達式,那就是變量提升方式)
函數提升方式: (整個函數聲明代碼塊提升到當前作用域的頂部,原先位置以不存在該代碼)
console.log(a); console.log(a()); var a = function () { console.log('a'); } function a () { console.log('function'); } console.log(a); console.log(a()); // 編譯后 function a () { // 函數提升在最前面 console.log('function'); } var a // 變量提升跟在后面 console.log(a); // 打印 a () { console.log('function')} console.log(a()); // 打印 undefined a = function () { // 變量賦值 console.log('a'); } console.log(a); // a () { console.log('a')} console.log(a()); // 打印 undefined
總結:
- 所有的聲明都會提升到作用域的最頂上去。
- let 不存在變量提升
-
同一個變量只會聲明一次,其他的會被忽略掉或者覆蓋掉。
-
函數聲明的優先級高於變量申明的優先級,並且函數聲明和函數定義的部分一起被提升。