es6之let详解

本文介绍了ES6中let的声明方式及其特点,包括不允许顶层对象window、不允许重复声明、不存在变量提升、有暂时性死区和块级作用域。还对比了var和let在不同场景下的表现,如变量覆盖、声明提前等问题,最后提及面试可能遇到的相关问题及解决办法。

新的声明方式:let
let方式存在以下特点:
1.不允许顶层对象window
2.不允许重复声明
3.不存在变量提升
4.暂时性死区
5.块级作用域
一丶不允许顶层对象windodw

var a = 5
console.log(a)  //这里浏览器会输出5

b = 6
console.log(b) //这是浏览器会输出6
	

都知道对象有delete方法,这只能删除对象上的属性

var a = 5
console.log(a) //这里会输出5

delete a
console.log(a) //这里还会输出5

b = 6
console.log(b) //这里会输出5
delete b
console.log(b) //但是这里会报错

这是我们用window打印出来,发现window下面的a还在,所以这是js最早设计时的问题,也被称之为最大的败笔的地方

var a = 5
console.log(a) //这里会输出5
delete a
console.log(window.a)

b = 6
console.log(b) //这里会输出5
delete b
console.log(window.b) //现在在window对象打印时,就会是undefined

但是,当我们用let来声明这些变量的时候,这些变量就不会挂载到window上

let a = 5
console.log(a) //这里会输出5
console.log(window.a) //现在在window对象打印时,就会是undefined

二丶不允许重复声明
1.当用var来声明变量时,后面写变量会覆盖新的变量

var a = 5
var b = 6
console.log(b) //这是输出6

2.当用let声明变量时

let a = 5
let a = 5
console.log(a) //报错 Uncaught SyntaxError: Identifier 'a' has already been declared

三丶不存在变量提升
1.当用var来声明时,这里就会存在声明提前的问题,函数也有相同问题

console.log(a) //浏览器输出undefined
var a = 5

// 相当于
var a
console.log(a)
a = 5

2.当let来声明时

console.log(a) //Uncaught ReferenceError: Cannot access 'a' before initialization,表示变量必须在声明之后使用

let a = 5

四丶暂时性死区
1.用var来声明,这种方式写法不会报错

var a = 123

if (true) {
  console.log(a) //123
  a = 'abc'
  console.log(a) //'abc'
  var a
}

2.用let来声明时,ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。简单来说就是{}区域内就形成自己的封闭作用域,此作用域不同于es5只存在的全局作用域和函数作用域

var a = 123

if (true) {
  console.log(a) //Cannot access 'a' before initialization
  a = 'abc'
  console.log(a) //
  let a
}

3.有些“死区”比较隐蔽,不太容易发现,代码都会从左往右开始执行

function bar(x = y, y = 2) {
  console.log(x)
  console.log(y)
}
bar(); // 报错 Cannot access 'y' before initialization

function bar(x = 2, y = x) {
  console.log(x)
  console.log(y)
}

bar(); // 会输出2 2

5.块级作用域
ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

for (var i = 0; i < 3; i++) {
  console.log(i) //在循环中会输出0,1,2
}

console.log(i) //这里会输出3
for (let i = 0; i < 3; i++) {
  console.log(i) //在循环中会输出0,1,2
}

console.log(i) //报错 i is not defined

面试可能会遇到的问题

for (var i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i) 
  })
}

大家想一下这里的i会输出什么,答案是3个3,原因就是setTimeout是一个异步操作,在js中有一个叫做事件循环机制,setTimeout会等到主线程空闲,并且时间到的时候执行,for循环是一个同步操作,当setTimeout执行时,for循环已经执行完成了,所以答案为3个3
想一想如果我们想得到0,1,2应该怎么做

 for (var i = 0; i < 3; i++) {
  (function (j) {
    setTimeout(function () {
      console.log(j) //这里会输出0,1,2
    })
  })(i)
}

这是我们采用闭包的写法,每一次匿名函数都会执行一次,并且把对应的参数传进去,不了解的朋友可以先去了解下闭包

当我们采用let方法时

for (let i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i) //这里就会输出0,1,2
  })
}

我们看一下在babel编译器中当es6被转换为es5写法时

"use strict";
var _loop = function _loop(i) {
  setTimeout(function () {
    console.log(i); //这里就会输出0,1,2
  });
};

for (var i = 0; i < 3; i++) {
  _loop(i);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值