ES6中的var, let, const

var, let, const

這三個東西, 經常會被問到。

彙總一下,基本上就是:

  • var, let, const 有什麼區別?
  • let, const 有沒有變量提升(hosting) ?
  • 什麼是 TDZ ?

首先, 我們先整體的看下區別:

針對這幾點, 我們一個個看。

首先, 我們還是先了解一下變量提升.

看個例子:

console.log(a) // undefined
var a = 1

這裏我們可以看到, 第一行中的a雖然還沒聲明, 但是我們用起來卻不會報錯。 這種情況, 就是聲明的提升。

其實也就是:

var a
console.log(a) // undefined
a = 1

但是, 如果是換成let , 情況就不一樣了:

image.png

要理解這個現象, 首先需要搞清楚提升的本質, 理解創建 javascript 變量的三個步驟

  1. 創建
  2. 初始化
  3. 賦值

爲了便於理解, 我們先看看var 的 創建、初始化和賦值 過程:


function foo(){
  var x = 1
  var y = 2
}

foo()

執行foo 時, 會有一些過程(部分過程):

  1. 進入 foo,爲 foo 創建一個環境。
  2. 找到 foo 中所有用 var 聲明的變量,在這個環境中「創建」這些變量(即 x 和 y)。
  3. 將這些變量「初始化」爲 undefined。
  4. 執行代碼
  5. x = 1 將 x 變量「賦值」爲 1
  6. y = 2 將 y 變量「賦值」爲 2

也就是說 va 聲明, 會在代碼執行之前就將 創建變量,並將其初始化爲 undefined

這就解釋了爲什麼在 var x = 1 之前 console.log(x) 會得到 undefined

接下來看 let 聲明的「創建、初始化和賦值」過程

// ...
{
  let x = 1;
  x = 2
}

我們看一下過程:

  1. 找到所有用 let 聲明的變量,在環境中創建這些變量
  2. 執行代碼(注意現在還沒有初始化)
  3. 執行 x = 1,將 x 「初始化」爲 1(這並不是一次賦值,如果代碼是 let x,就將 x 初始化爲 undefined)
  4. 執行 x = 2,對 x 進行「賦值」

這就解釋了爲什麼在 let x 之前使用 x 會報錯:

let x = 'global'
{
  console.log(x) // Uncaught ReferenceError: x is not defined
  let x = 1
}

原因有兩個

  1. console.log(x) 中的 x 指的是下面的 x,而不是全局的 x.
  2. 執行 log 時 x 還沒「初始化」,所以不能使用(也就是所謂的 TDZ, tempory dead zone, 暫時死區)

說到這裏, 就都清楚了:

  1. let 的「創建」過程被提升了,但是初始化沒有提升。
  2. var 的「創建」和「初始化」都被提升了。

function 也是類似的,而且function 的「創建」「初始化」和「賦值」都被提升了。

這一點, 感興趣的朋友可以自己實驗一下。

算了, 直接給個例子吧:

<script>
bar()
 
function  bar(){
  console.log(2)
}
</script>

JS 引擎會有一下過程:

  1. 找到所有用 function 聲明的變量,在環境中「創建」這些變量。
  2. 將這些變量「初始化」並「賦值」爲 function(){ console.log(2) }
  3. 開始執行代碼 fn2()`

也就是說 function 聲明會在代碼執行之前就「創建、初始化並賦值」。

這裏做一下簡單的總結:

  1. 函數提升優先於變量提升函數提升會把整個函數挪到作用域頂部變量提升只會把聲明挪到作用域頂部
  2. var存在提升,我們能在聲明之前使用。
  3. letconst 因爲存在暫時性死區不能在聲明前使用
  4. var全局作用域下聲明變量, 會導致變量掛載在window上, 而另外兩者不會
  5. let 和 const的作用基本一致,但是後者聲明的變量不能再次賦值。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章