ECMAScript 6 之变量那些事

ECMAScript 6 已经正式发布一个月了,接下来会分享一些学习笔记以及自己的理解.

新增的关键字 let与const

一直以来,javascript 都是用var来申明变量

function foo(){
  var a = 1;
  console.log(a)
}

foo(); //1

现在我们多了两个新的小伙伴:let与const

let命令

function foo(){
  let a = 1;
  console.log(a)
}

foo(); //1

这样看起来,与var没有什么区别,我们看接下来的例子

if(true){
  var a =1;
}

console.log(a) //  1
if(true){
  let a =1;
}

console.log(a) //  Error: a is not defined

在 for函数里

for (var i = 0; i < 10; i++) {

}

console.log(i) //  10
for (let i = 0; i < 10; i++) {

}

console.log(i) //  Error: i is not defined

上面的例子说明了,let只在块级作用域里有效.而var在以上情况下,是作为一个全局变量存在的;

我们再举一个例子:

var arr = [];
for (var i = 0; i < 3; i++) {
  arr.push(function(){
    return i;
  })
}

console.log(arr[0]()) //3
console.log(arr[1]()) //3
console.log(arr[2]()) //3

数组里每一个function运行后,输出的i都是10;

这好像跟我们预想的结果不太一样.

在这里var i 作为一个全局的变量,每一次 i++后,都会覆盖之前的值

所以arr里的function运行后返回的i,都是最后都是返回的全局变量 i;

var arr = [];
for (let i = 0; i < 3; i++) {
  arr.push(function(){
    return i;
  })
}

console.log(arr[0]()) //0
console.log(arr[1]()) //1
console.log(arr[2]()) //2

在这里 let i是为一个局部变量. arr里的funtion运行后,都是返回局部的i,每一次都是一个新的变量. 所以function运行后输出的都是相对应的值;

如果用var怎么做到以上的效果呢?

var arr = [];
for (var i = 0; i < 3; i++) {

  (function(i){
    arr.push(function(){
      return i
    })
  })(i)

}

console.log(arr[0]()) //0
console.log(arr[1]()) //1
console.log(arr[2]()) //2

我们在for函数里,新增一个自执行的函数,把i传进这个自执行函数里. 每一次运行就相当于重新在自执行函数里重新申明了一个i, 自执行函数里的i就不会受到外面的全局i的影响了;

变量提升

console.log(foo) // undefined

var foo =1;

javascript 对被var申明过的变量,如果在被赋值之前使用都先会被赋值为undefined,并不会报错

console.log(foo) // 报错

let foo =1;

用let定义的变量,却报错了.let不支持变量提升, 必须得先申明后使用

暂时性死区 (TDZ)

由于let的变量必须得先申明再使用; 于是这里抛出了一个叫”暂存死区”的概念; 什么叫暂存死区呢?

{
  //暂时性死区开始
  console.log(foo) // 报错

  //foo被声明后暂时性死区结束
  let foo =1;
  console.log(foo);
}

在块级作用域下,从作用域执行的一开始,到变量被申明的这一段,叫做暂存死区.

在暂存死区里使用变量,是不允许的.

不能重复申明

var foo = 1;
var foo = 2
console.log(foo) //2
let foo = 1;
let foo = 2; //报错
console.log(foo);

由let申明的变量是不允许重复申明的;

const命令

const关键字申明的是常量, 什么是常量? 由const申明出来的’变量’,是只读不允许修改的.

var foo=1;
foo =2; //2
const FOO=1;
FOO =2; //报错 "FOO" is read-only

一般来说,常量会以全大写的方式来命名;

const也跟let一样有着不能变量提升,暂时性死区,不允许重复申明,以及只能在所在的块级作用域下申明后使用等特性.

本文链接:

https://alili.tech/archive/573a0170/