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的作用基本一致,但是后者声明的变量不能再次赋值。
发布了171 篇原创文章 · 获赞 499 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/qq_43258252/article/details/102475233