var const 和 let的区别

26 阅读2分钟

var

  • 允许重复的变量声明:导致数据被覆盖
  • 变量提升:怪异的数据访问、闭包问题
  • 全局变量挂载到全局对象:全局对象成员污染问题

let

  • ES6不仅引入let关键字用于解决变量声明的问题,同时引入了块级作用域的概念
  • 块级作用域:代码执行时遇到花括号,会创建一个块级作用域,花括号结束,销毁块级作用域

声明变量的问题

  • 全局变量挂载到全局对象:全局对象成员污染问题,let声明的变量不会挂载到全局对象

  • 允许重复的变量声明:导致数据被覆盖,let声明的变量,不允许当前作用域范围内重复声明,在块级作用域中用let定义的变量,在作用域外不能访问

  • 变量提升:怪异的数据访问、闭包问题,使用let不会有变量提升,因此,不能在定义let变量之前使用它

  • 底层实现上,let声明的变量实际上也会有提升,但是,提升后会将其放入到暂时性死区,如果访问的变量位于暂时性死区,则会报错:“Cannot access 'a' before initialization”。当代码运行到该变量的声明语句时,会将其从暂时性死区中移除。

  • 在循环中,用let声明的循环变量,会特殊处理,每次进入循环体,都会开启一个新的作用域,并且将循环变量绑定到该作用域(每次循环,使用的是一个全新的循环变量)

  • 在循环中使用let声明的循环变量,在循环结束后会销毁

const

  • const和let完全相同,仅在于用const声明的变量,必须在声明时赋值,而且不可以重新赋值。

  • 常量不可变,是指声明的常量的内存空间不可变,并不保证内存空间中的地址指向的其他空间不可变。

  • 常量的命名

    • 特殊的常量:该常量从字面意义上,一定是不可变的,比如圆周率、月地距地或其他一些绝不可能变化的配置。通常,该常量的名称全部使用大写,多个单词之间用下划线分割
    • 普通的常量:使用和之前一样的命名即可
  • 在for循环中,循环变量不可以使用常量

console.log(a); // undefined  ->  a已声明还没赋值,默认得到undefined值
var a = 1;
console.log(b); // 报错:b is not defined  -> 找不到b这个变量
let b = 2;
console.log(c); // 报错:c is not defined -> 找不到c这个变量
const c = 3;