let const 的工作原理

60 阅读2分钟

let const的起源

let const是es6提出的,用于声明变量的指令

为什么要引入let const

js只有全局作用域跟函数作用域,没有全局作用域,这样可能会带来一些问题,比如

内层变量会覆盖外层变量

var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}

f(); // undefined

用来计数的变量会变成全局变量

var s = 'hello';

for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); // 5

块级作用域是怎么实现的

function foo(){
    var a = 1
    let b = 2
    {
      let b = 3
      var c = 4
      let d = 5
      console.log(a)
      console.log(b)
    }
    console.log(b) 
    console.log(c)
    console.log(d)
}   
foo()
  • 当我们执行代码的时候,首先会创建代码执行的上下文,通过var声明的变量,会被放在变量环境里,通过let声明的变量,会被放在词法环境
  • 在函数的作用域内部,通过let声明的变量并没有放到词法环境中。
  • 当函数执行到函数的块状作用域时,会将函数内部let声明的变量,放到词法环境一个单独的区域中,这时候这个区域的变量跟外层词法环境的变量互不干扰。
  • 词法环境内部,是一个栈结构,底层放着的,是最外层let声明的变量,当执行到一个块状作用域时,遇到新let声明的变量,就会将该变量压入栈顶(函数执行上下文的工作原理),然后执行完再弹出,如此执行下去。

ps

  • es6的块状作用域,必须声明在大括号内,如果没有,则默认没有块状作用域。
  • const的不变,指的是引用地址不能改变,所以对于object对象其实可以发生修改的。

小例子

执行下面这段代码,会发生什么,是为什么?

// 第一种写法,报错
if (true) let x = 1;

// 第二种写法,不报错
if (true) {
  let x = 1;
}