专栏首页前端菜鸟变老鸟ES6(一):let和const

ES6(一):let和const

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/caomage/article/details/83586048

ES6(一):let和const

一、let

1. let基本用法

  相当于var,但是又与var不同,因为let声明的变量只能在let所在的代码块中有效。   从以下两段代码以及对应的输出结果可以很明显的看出var与let的区别。 code:

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

result:

0
1
2
3
4
5

code:

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

result:

0
1
2
3
4
ReferenceError: i is not defined

2. 块级作用域

  众所周知,在ES5中只有全局作用域和函数作用域,没有我们所谓的块级作用域。   这不禁让我想起一个面试题: code:

for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i);
    }, 1000);
}

console.log(new Date, i);

  问:上面这段代码输出的结果是什么?   仔细琢磨一下我们很容易得出正确的答案:

result:

2018-10-31T06:55:30.020Z 5
2018-10-31T06:55:31.021Z 5
2018-10-31T06:55:31.021Z 5
2018-10-31T06:55:31.022Z 5
2018-10-31T06:55:31.022Z 5
2018-10-31T06:55:31.022Z 5

  仔细看一下发现:由于setTimeout会被JavaScript延迟执行,因此是先输出最底部的console.log,隔一秒之后再执行循环里面的consol.log,此时i已经全部是5。   那我们怎么样才能使输出结果变成想要的0,1,2,3,4呢?   明白了let的原理之后其实问题变得很简单: code:

for (let i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(new Date, i);
    }, 1000);
}

console.log(new Date, i);

  这样就行了吗? result:

ReferenceError: i is not defined

  哈哈,刚刚还说过let只在所在的代码块里面有效,这里最外层的console.log很明显找不到i,所以报出引用错误。想要得到正确答案其实还需要去掉最后一行console.log。   当然这个题目要搁以前的话,首先想到的解决方案应该是IIFE(Immediately Invoked Function Expression:声明即执行的函数表达式)来解决闭包造成的问题。 code:

for (var i = 0; i < 5; i++) {
    (function(j) {  
        setTimeout(function() {
            console.log(new Date, j);
        }, 1000);
    })(i);
}

console.log(new Date, i);

result:

2018-10-31T07:17:45.825Z 5
2018-10-31T07:17:46.827Z 0
2018-10-31T07:17:46.827Z 1
2018-10-31T07:17:46.827Z 2
2018-10-31T07:17:46.827Z 3
2018-10-31T07:17:46.827Z 4

  由此我们是不是就可以得出一个结论,有了let,我们就可以抛弃IIFE了?   这个暂时还不好说,我们还是继续看看let的其他特性。

3. 没有变量提升

  var命令会产生变量提升的现象,这使得js这门语言变得并不严谨,这一点是特点也是鸡肋。用var声明的变量,如果我们在声明之前使用,则它的值为undefined。   而当我们用let定义变量时,就必须严格按照先定义再使用的原则了,反之则会抛出一个大大的引用错误(ReferenceError),显然这更符合人们的使用习惯。 code:

console.log(a);
var a = 2;

console.log(b);
let b = 2;

result:

undefined
ReferenceError: b is not defined

4. 暂时性死区及不能重复声明

  ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。   总之,在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。   “暂时性死区”也意味着typeof不再是一个百分之百安全的操作。   let不允许在相同作用域内,重复声明同一个变量。

二、const

1. const基本用法

  const命令是声明一个常量,用法和let一样。

  • 和let的相同之处是:
    • const与let作用域相同,都是只在声明的代码块中起作用
    • const也不会提升所声明的常量
    • const也不能重复声明
  • 不同之处是const声明的常量在声明时就必须赋值,因为一旦声明就不能改变改常量的值

2. 真的不能改变吗?

  const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。 code&result:

const a=1;
a=2;//TypeError
const obj={
    b:3,
    c:4
}
obj.b=5;
console.log(obj);//{b:5,c:4}

参考资料

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • ES6(三):变量的解构赋值

    解构赋值语法是一个Javascript表达式,这使得可以将值从数组或属性从对象提取到不同的变量中,文中主要讲数组的解构赋值、对象的解构赋值、字符串的解构赋值、数...

    从入门到进错门
  • Webkit底层原理(1)--Webkit架构和模块

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 ...

    从入门到进错门
  • JS自定义右键菜单—复制到粘贴板(jQuery和原生JS实现)

    从入门到进错门
  • 这5个 console.log() 技巧帮你提高工作效率

    我们知道 console.log(message)用法很简单,表示将参数message 打印到控制台上。

    前端小智@大迁世界
  • Appium系列|Appium环境搭建(一)

    Appium是一种现在市面上很流行的自动化测试的工具,可以用来进行Android端、iOS端、Windows应用的自动化。对于移动端应用,它既支持应用内...

    测试邦
  • Kubernetes & Istio 汉化工作流支持工具简介

    本项目支撑了 Istio 和 Kubernetes 的文档中文化流程,它以 Github Issue 为工作对象,通过 Chatbot 和 Webhook 相结...

    崔秀龙
  • 面试想拿 25K,HR 却说只值 15K,技术人该如何反驳?

    知乎上看到这样一个问题:面试的时候想拿xx,HR却说我只值xx,这种情况下应该怎么办?

    养码场
  • 小心新型“抢注域名”诈骗 !

    浙江的林老板花一万多元注册的域名,有人说要用百万元收购。喜不自胜的他又听信了对方的建议掏钱让他们帮忙抢注类似域名坐等赚钱。前前后后花了47万元,最后人却不见了,...

    躲在树上的域小名
  • JavaScript 为什么要有 Symbol 类型

    Symbols 是 ES6 引入了一个新的数据类型 ,它为 JS 带来了一些好处,尤其是对象属性时。 但是,它们能为我们做些字符串不能做的事情呢?

    前端小智@大迁世界

扫码关注云+社区

领取腾讯云代金券