Skip to content

深入理解let, const #12

Description

@tiger5wang

let/const 和var的区别

想必涉及let/const 最多的问题就是 和 var的区别了,一般的解答是这样的:

  • let/const 声明的变量的作用域是块级的,var 声明的变量的作用域是全局的;
  • let/const 不能重复声明已存在的变量,var 可以重复声明已存在的变量;
  • var 不能限制对变量的修改,const 声明的变量不能修改;
  • let/const 有暂时死区,不能提升。

特殊情况

for(var i=0; i<10;i++){
    setTimeout(function(){
        console.log(i)
    }, 0)
}
// 打印结果为 10个 10,原因都知道,就不多解释了

但是 将 var 改为let 后,结果就不一样了

for(let i=0; i<10;i++){
    setTimeout(function(){
        console.log(i)
    }, 0)
}
// 打印结果: 0 1 2 3 4 5 6 7 8 9

这是为什么呢?
for 循环头部的 let 不仅将 i 绑定到了 for 循环的块中,事实上它将其重新绑定到了循环 的每一个迭代中,确保使用上一个循环迭代结束时的值重新进行赋值。
可以这样理解:

for(var i=0; i<10;i++){
    let j= i;
    setTimeout(function(){
        console.log(j)
    }, 0)
}
// 打印结果: 0 1 2 3 4 5 6 7 8 9

关于暂时死区,又是什么原因呢,为什么 var 却没有呢?

{
    console.log(x);
    let x
}
{
    console.log(x);
   const x
}
// 这两个都会报一样的错 
// Uncaught ReferenceError: Cannot access 'x' before initialization
// x 被初始化之前不能使用

// 但是使用var 声明却不会报错
{
   console.log(x);
   var x
}
// undefined

报错的内容是 “初始化之前不能使用”,那么这就涉及到了变量的声明过程了:

创建、初始化、赋值

function 声明的「创建、初始化和赋值」过程

fn2()
function fn2(){
  console.log(2)
}
  • 找到所有用 function 声明的变量,在环境中「创建」这些变量。
  • 将这些变量「初始化」并「赋值」为 function(){ console.log(2) }。
  • 开始执行代码 fn2()
    也就是说 function 声明的代码, 在执行代码之前就已经 【创建、初始化、赋值】了。

var 声明【创建、初始化、赋值】的过程:

  • 找到用 var 声明的变量, 在环境中 【创建】这些变量;
  • 将这些变量【初始化】 为 undefined;
  • 执行代码
  • 给变量赋值

let/const 声明【创建、初始化、赋值】的过程:

{
  let x = 1
  x = 2
}
  • 找到let/const 声明的变量,在环境中 【创建】这些变量;
  • 执行代码(注意现在还没有初始化,这是最重要的一点);
  • 执行 x=1,将 x 【初始化】为1,(注意此处不是赋值,如果是 let x; 则将 x 初始化为 undefined)
  • 执行 x =2;对 x 进行【赋值】

这就解释了 为什么在 let x 之前使用 x 会报错:

  • console.log(x) 是已经声明了 x ,所以这个 x 就是块内部的 x , 不是外部的 x
  • 但是此时只是创建了 x ,还没有初始化,所以不能使用,

关于变量提升的总结:

  • let 的「创建」过程被提升了,但是初始化没有提升。
  • var 的「创建」和「初始化」都被提升了。
  • function 的「创建」「初始化」和「赋值」都被提升了。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions