重温JavaScript(lesson1): 关于ES6中的let

说明:第一次写作,部分内容的出处已经无法查找,对提供帮助的大佬表示感谢。

使用let语句,允许你在JavaScript中创建块范围局部变量。let语句是在JavaScript的  ECMASript 6标准中引入的。

关于let的使用要注意如下几点:

1.let声明的变量没有变量提升

首先look look什么是变量提升。JavaScript 中,函数及变量的声明都将被提升到函数的最顶部,变量可以在使用后声明,也就是变量可以先使用再声明。

用var声明的变量是存在变量提升的,看一个栗子:

function getValue(condition) {
  console.log(value);
  if(condition){
    var value = "blue"
    return value;
  } else {
    console.log(value)
    return null
  }
}

看一下给condition传入true和false之后的调用结果:

getValue(true);
//undefined

getValue(false);
//undefined
//undefined

代码没有报错,而是输出value的值为undefined。这是因为value的声明被提到了函数的最顶部,相当于如下的代码:

function getValue(condition) {
  var value;
  console.log(value);
  if(condition){
    value = "blue"
    return value;
  } else {
    console.log(value)
    return null
  }
}

在JS中一个已经声明但没有赋值的变量的值是undefined。所以传参为true的时候输出一次undefined,传参为false的时候输出两次undefined。

下面看一下,如果我们将var改为let来声明value的情况:

function getValue(condition) {
  console.log(value);
  if(condition) {
    let value = "blue";

    return value;

  } else {
    console.log(value);
    return null;
  }
}

getValue(true)
//Uncaught ReferenceError: value is not define at getValue

 

我们看到了,用let声明的变量是不存在变量提升的,所以使用的时候要注意啦,先声明再使用!

2.暂时性死区(TDZ)的概念

至此,我们知道了:let声明的变量是不会提升的。在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称TDZ) 。

3.let禁止重复声明

还是先看一下使用var重复声明变量的情况:

var count = 30;
var count = 40;
console.log(count);//40

可以看到使用var关键字,可以使用相同名称声明多个变量,完全没问题,没有报错。这也是为什么早期使用var声明变量的时候会造成覆盖和名字冲突的原因。

在看看使用ES6的let声明同名变量的情况:

let count = 30;
let count = 40;

图片

图片

我们发现,这样做的话,在编辑器中编译不会通过并且浏览器会报错。

4.let声明的变量只在块级作用域内有效

 

说到了作用域,这可是一个大话题,以后再专门说说作用域。在ES6没有诞生之前,JS有全局作用域、函数作用域,但是没有块级作用域。ES6中新增了块级作用域。

本小节的标题是“let声明的变量只在块级作用域内有效”,这有什么可说的呢?我们谈谈块级作用域有什么优势?为什么需要块级作用域?

这就要扯到了ES5在没有块级作用域时出现了哪些问题?先来看代码:

var funcs = [];
for(var i=0;i<10;i++) {
  funcs.push(function(){
    console.log(i);
  })
}
funcs.forEach(function(func){
  func();
})

猜猜这一小段代码的会输出什么?有经验的都知道哦!会输出10次10,并不是我们期望的0-9。

图片

为什么是这样的?因为i是使用var声明的全局变量,在全局作用域内有效,循环结束后它的值会变为10。而funcs中的每一个函数的console.log()语句引用的是同一个i,所以值都为10。

怎么解这个问题呢?ES5中的一种方案是利用IIFE(立即调用函数表达式),看代码:

var funcs = [];
for(var i=0;i<10;i++) {
  funcs.push((function(value){
    return function(){
      console.log(value);
    }
  }(i)));
}

funcs.forEach(func => {
  func();
})

这回funcs数组中每次push进去的是一个IIFE,每次循环时i作为参数传给形参value,这样就能够保持对此值的引用,可以达到我们想要的结果:

好麻烦,好多括号,懵了...  好了,看一下用let解决能有多香~

var funcs = [];

for(let i=0;i<10;i++) {
  funcs.push(function(){
    console.log(i);
  })
}

funcs.forEach(func => {
  func();
})

图片

注意代码中的循环变量i使用了let进行声明,let声明的变量只在块级作用内有效,for循环的时候每一次i都是一个新值。说的直白些,每次循环let声明都会创建一个新变量i,并将其赋值为i的当前值。

嗯~,有关let的内容,我们简单的重温到这里,接下来看几道和let有关的面试题检测一下知识的掌握情况吧~

5.和let相关的几个面试题

1.下面代码的输出是什么?

图片

图片

2.下面代码的输出是什么?

图片

好了,这就是本次的全部内容了。如有错误,请不吝指正。温故而知新,欢迎和我一起重温旧知识,攀登新台阶~

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重温新知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值