es6-let和const

咱们知道es5中 var 声明变量是做用于在全局或函数做用域,而且全局声明的变量还会做为 window 对象的属性。这样会增长程序错误的产生和不可控。es6

变量提高

在全局或者函数做用内用 var 声明的变量,在js预编译阶段会提高到当前做用域的顶部,这就是变量提高。以下代码:函数

function getValue(condition) {
  if (condition) {
    var value = 'red';
  } else {
    console.log(value); // undefined
  }
  console.log(value);  // undefined
}
复制代码

以上代码至关于把变量value放在当前做用域先声明,因此才能在if块外和else块访问到,都会输出 undefinedpost

function getValue(condition) {
  var value;
  if (condition) {
    value = 'red';
  } else {
    console.log(value); // undefined
  }
  console.log(value);  // undefined
}
复制代码

let声明

从上面的能够看出 var 声明的变量没有块级做用域的概念,因此es6引入了let 声明,并绑定在当前的块做用域,块做用域外访问报错,以下:ui

function getValue(condition) {
  if (condition) {
    let value = 'red';
  } else {
    console.log(value); // ReferenceError: value is not defined
  }
  console.log(value); // ReferenceError: value is not defined
}
复制代码

禁止重复声明。在同一个块中不能用 let 声明已经存在的标识符,不然会报错。若是是嵌套的做用域中重复声明,则不会报错。es5

var count = 30;
let count = 30;  // SyntaxError: Identifier 'count' has already been declared

if (true) {
  let count = 30;  // 不会报错
}
复制代码

const声明

在es6引入const 来进行常量的声明。他和前面的 let 同样有块做用域绑定和不准重复声明的特性。可是const 必需要在声明的阶段进行初始化,而let 不用。spa

let count;   // 不会报错

const count;  //SyntaxError: Missing initializer in const declaration

const count = 30;  // 正确声明
复制代码

const 声明的变量不能再赋值。若是变量是引用类型,能够修改对象的属性值,但不能够从新修改绑定的对象。code

const count = 20;
count = 30;  // TypeError: Assignment to constant variable.

const obj = {};
obj.name = 'wozien';
复制代码

临时死区

因为letconst 不存在变量提高,因此在声明前使用该变量会报错。由于在声明前,该变量存在于所谓的临时死区(TDZ)。对象

if (true) {
  console.log(typeof value);
  let value = 'red'; // ReferenceError: value is not defined
}
复制代码

当变量声明后,就会从临时死区移出,后续可正常访问。注意的是,TDZ是针对当前的块做用域而言,因此以下能够正确运行:作用域

console.log(typeof value); // undefiend
if (true) {
  let value = 'red';
}
复制代码

在循环中的区别

var 声明的循环变量,会在循环后外部可正常访问,而且值为跳出循环的值。let 声明的变量则只在循环体内有效,以下:开发

for (var i = 0; i < 5; i++) {}
console.log(i); // 5

for (let i = 0; i < 5; i++) {}
console.log(i); // ReferenceError: i is not defined
复制代码

在利用 var 声明的循环中建立函数会变得很艰难,由于函数执行的时候是迭代完的最终,以下:

const func = [];
for (var i = 0; i < 3; i++) {
  func.push(() => {
    console.log(i);
  });
}
func.forEach(func => func()); // 2 2 2
复制代码

咱们能够利用当即执行函数(IIFE)解决这个问题,让每一个函数最终保存的是迭代过程当中变量的副本。

for (var i = 0; i < 3; i++) {
  (function(value) {
    func.push(() => console.log(value));
  })(i);
}
复制代码

在es6中循环里面 let 声明能够用来简化上面IIFE的实现过程,他会在每次迭代过程当中从新声明一个同名变量i,值为当前的迭代i的值,因此循环体内的函数使用的都是i值的副本。

for (let i = 0; i < 3; i++) {
  func.push(() => console.log(i));
}
func.forEach(func => func()); // 0 1 2
复制代码

若是把 let 改为 const, 在第二次迭代的时候会报错,由于 const 不准从新赋值。而对于 for-infor-of 循环二者均可以正常的运行。

const obj = {
  a: 1,
  b: 2,
  c: 3
};
const func = [];

for (let key in obj) {
  func.push(() => console.log(key));
}

func.forEach(func => func());  // a b c
复制代码

若是把let 替换成 var ,将会输出3个c。由于 for-infor-of 每次都只会从新声明一个新的副本key。

在全局中的绑定

利用 var 在全局声明变量,会做为window对象的一个属性存在,而 letconst 则不会。

var a = 1;
let b = 2;
const c = 3;

console.log(window.a); // 1
console.log(window.b); // undefined
console.log(window.c); // undefined
复制代码

小结

es6中的letconstvar 区别以下:

  • 绑定块做用域,不存在变量提高
  • 不容许重复定义
  • 声明前不容许使用变量
  • for 循环中每次建立新的副本
  • 全局声明不做为 window 属性

在咱们平时的开发中,能够默认使用const。在确认须要改变变量的值时才使用let,能够必定程序上防止代码的错误产生。

>>>原文地址

相关文章
相关标签/搜索