es6之let const 和var区别剖析

144 阅读3分钟

ES6 一共有 6 种声明变量的方法。

var和function(声明的全局变量,是顶层对象的属性(window)) let和const和class (声明的全局变量,不属于顶层对象的属性) import

区别分为以下几个方面:

1.块级作用域

2.不存在变量提升

3.暂时性死区

4.不可重复声明

5.let const 声明的全局变量不会挂在顶层对象上

一.什么是块级作用域?为什么需要块级作用域?用在var let/const的区别?

1.只要被包裹在在{}中都是一个块级作用域。例如:if、for、function、或者是直接只写一个{}。

 function method(){
  let n = 5;
  {
    let n = 10;
    console.log(n); // 10 内层的n
  }
  console.log(n); // 5 当前层的n
}  

2.在es5里只有全局作用域和函数作用域,这样会有很多麻烦的事情。

(1)内层变量可能覆盖外层变量 ( 函数,变量声明被解释器"提升"到方法体的最顶部,初始化不会提升)

var a = 2;              // 声明a 并初始化为2
function method(){      //
  console.log(a);       //undefined
  var a = 3;            //作用域为整个函数
}
method();

(2)用来计数的循环变量泄露为全局变量

var s = 'hello';
for (var i = 0; i < s.length; i++) {        // 此处的i是全局变量
    console.log(s[i]);                      // i为此次for循环使用的变量
} 
console.log(i);                             // 5 全局范围都可以读    

二.不存在变量提升

// var 的情况
   console.log(foo); // 输出undefined
   var foo = 2;
// let 的情况
  console.log(bar); // 报错ReferenceError
  let bar = 2;

三.暂时性死区

定义:该区域只要存在let,const,进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

        var tmp  = '123'
	if (true) {    //进入这个区域,tmp已经存在了,只是不可获取
	  tmp = 'abc'; // ReferenceError  
          let tmp;
	}

暂时性死区和不能变量提升的意义:为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。

四.不可重复声明

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

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

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

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

五.let const 声明的全局变量不会挂在顶层对象上

var a = 1;
window.a // 1

let b = 1;
window.b // undefined

此处是let var在块级作用域和函数中的声明

es5中,函数只能在顶层作用域和函数内部声明,不能再块级作用域声明。但是浏览器不遵守这个规定。

if {
  function f() {}      // 对于es5应该报错,但是浏览器是正常运行的
}

es6中,允许在块级作用域声明函数,声明函数的行为等同于let

function f() { console.log('I am outside!'); }

(function () {
  if (false) {
    // 重复声明一次函数f
    function f() { console.log('I am inside!'); }
  }

  f();
}());
 在es5中,内部函数提升,则先打印'I am inside!
 在es6中,没有提升,则先打印'I am outside!',但是上段代码在支持es6的浏览器中报错,因为浏览器的实现可以不遵守上面的规定,有自己的方式。

方式为:

允许在块级作用域内声明函数。

函数声明类似于var,即会提升到全局作用域或函数作用域的头部。

同时,函数声明还会提升到所在的块级作用域的头部。

剖析const

保证的并不是变量的值不得改动,保存的只是一个指向实际数据的指针,保证这个指针是固定的(即总是指向另一个固定的地址)

const foo = {};
// 为 foo 添加一个属性,可以成功
foo.prop = 123;
// 将 foo 指向另一个对象,就会报错,因为不能指向另一个地址
foo = {}; // TypeError: "foo" is read-only

let、const使用场景:

  1. let使用场景:变量,用以替代var。

  2. const使用场景:常量、声明匿名函数、箭头函数的时候。