ES6之let const

在ES6之前,js只有全局作用域和函数作用域,声明变量一般用var,否则就是全局变量。 ES6,新增了块级作用域,声明变量多了两个关键字let,const。

块级作用域

对于从安卓转到前端的我来说,ES5没有块级作用域,还是很容易造成代码理解的错误的。

for(var i=0;i<10;i++){
    //do something...
}

console.log(i);//   10

按照java的习惯,i 变量应该是只在for代码块里生效的。但是js里,这样声明的 i 就是全局变量。这就是因为js没有块级作用域。

ES6新增了块级作用域。既let,const,让{ }之间拥有了块级作用域。

{
    let t = 0;
}

console.log(t); //Uncaught ReferenceError

for(let i=0;i<10;i++){
    //do something...
}

console.log(i); //Uncaught ReferenceError

let关键字

基本用法

{
    let t = 0;
    var m = 1; 
}

console.log(t); //Uncaught ReferenceError
console.log(m); //1

上面代码在代码块之中,分别用let和var声明了两个变量。然后在代码块之外调用这两个变量,结果let声明的变量报错,var声明的变量返回了正确的值。这表明,let声明的变量只在它所在的代码块有效。

不存在变量提升

let不像var那样会发生“变量提升”现象。所以,变量一定要在声明后使用,否则报错。

console.log(foo); // 输出undefined
console.log(bar); // 报错ReferenceError

var foo = 2;
let bar = 2;

上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误,所以使用let请先声明,后使用。

暂时性死区(temporal dead zone)

只要块级作用域内存在let命令,它所声明的变量在声明之前都是不可用的,即使全局变量中存在同名变量。

var tmp = 111if (true) {
  // TDZ开始
  tmp = 'abc'; // ReferenceError
  console.log(tmp); // ReferenceError

  let tmp; // TDZ结束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}

上面代码中,存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp,导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ)。

不允许重复声明

let不允许在相同作用域内,重复声明同一个变量。

// 报错
function () {
  let a = 10;
  var a = 1;
}

// 报错
function () {
  let a = 10;
  let a = 1;
}

因此,不能在函数内部重新声明参数。

function func(arg) {
  let arg; // 报错
}

function func(arg) {
  {
    let arg; // 不报错
  }
}

const关键字

const特性与let基本一致。

const声明一个只读的常量。一旦声明,常量的值就不能改变。

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.

上面代码表明改变常量的值会报错。

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const a = 1;
a // 1

a = 3;
// TypeError: Assignment to constant variable.


const b = { a:1,c:2 };
b //  { a:1,c:2 }

b = {};
// TypeError: Assignment to constant variable.

b.a = 3;

b.c =12;

b //  { a:3,c:12 }

js的变量可以分为两类,值类型,引用类型。

引用类型,变量其实储存的可以理解为一个内存地址,真正的内容储存在内存地址所指向的内存。

const修饰引用类型时,const只是限制了引用的地址不能改变,并不会限制地址指向的内容不改变。

使用 Discussions 讨论 Github 上编辑