var、let、const

95 阅读3分钟

1. var

var声明的变量只能是全局或者整个函数块的作用域

1.1 变量提升

由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫做“hoisting”。“hoisting”就像是把所有的变量声明移动到函数或者全局代码的开头位置。

bla = 2
var bla;

因此,建议始终在作用域顶部声明变量,这可以清楚知道哪些变量是函数作用域(本地),哪些变量在作用域链上解决。重要的是,提升将影响变量声明,而不会影响其值的初始化。当到达赋值语句时,该值将确实被分配。

function do_something() {
  console.log(bar); // undefined
  var bar = 111;
  console.log(bar); // 111
}

// is implicitly understood as:
function do_something() {
  var bar;
  console.log(bar); // undefined
  bar = 111;
  console.log(bar); // 111
}

1.2 隐式全局变量

没有被声明的变量,变为了全局变量

function b() { // 当b被调用时,
    x = 3;  
    y = 4;  
    z = 5;  
  }         

b();     // 调用b时创建了全局变量想x, y, z。

2 let const

const, let允许你声明一个作用域被限制在 块级中的变量、语句或者表达式。与 var 关键字不同的是, var声明的变量只能是全局或者整个函数块的。 var 和 let 的不同之处在于后者是在编译时才初始化(见下面)。 const声明的基本类型值不可改变

2.1 块作用域

let、const声明的变量只在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。

function varTest() {
  var x = 1;
  {
    var x = 2;  // 同样的变量!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  {
    let x = 2;  // 不同的变量
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

2.2 重复声明

if (x) {
  let foo;
  let foo; // SyntaxError thrown.
}

尤其是在switch中会遇到此错误,解决方法可在case后加上代码块

let x = 1;
switch(x) {
  case 0:
    let foo;
    break;

  case 1:
    let foo; // SyntaxError for redeclaration.
    break;
}

2.3 暂存死区

let const 在声明之前使用会报错,typeof也避免不了

{
  typeof a;
  let a = 1;
}

3 三者区别

3.1 var 和 let、const的不同点

  • var只能在function,全局中形成作用域;let、const会在代码块中形成块级作用域

  • 暂时性死区

  • var可重复声明,let、const不可重复声明

  • let、const声明的全局变量不会挂在顶层对象下面

3.2 let const的区别

  • const 声明之后必须马上赋值,否则会报错

  • const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改 const 变量不能修改指针,但是可以修改值

const person = {
    name: "蛙人",
    age: 23
}
person.age = 18 // 没问题
person = {} // SyntaxError for redeclaration.