【ES6复习】let和const

栏目: JavaScript · 发布时间: 6年前

内容简介:在使用虽然不存在变量提升的问题,但是如代码示例,由于大括号内声明了let,导致运行时出现ReferenceError错误。

letconst 作ES6的一大新特性,日常使用最多,那么我们真的清楚他的特性了吗,以及了解Babel转换后的结果吗?

ES6 之前

var
var foo = -1;
 // window.foo === -1

function fun() {
    // 未抛出异常,声明提前
    console.log('-1:', foo);

    var foo = 0;
    console.log('0:', foo);

    if (true) {
        console.log('1:', foo);
        var foo = 1;
        console.log('2:', foo);
    }

    // foo === 1 覆盖了前面声明的foo变量
    console.log('3:', foo);
}
fun();
// undefined、0、0、1、1

在使用 var 进行循环时经常会出现如下问题,那么ES6中存在这样的问题吗?

for (let i = 0; i < 5; i++) {
  setTimeout(function(){
      console.log(i);
  }, 1000)
}
// 结果:5, 5, 5, 5, 5 并没有按照要求打印出0-4

ES6 let

不允许重复声明

全局对象不再是顶层对象

var a = 1;
console.log(window.a) // 1

let b = 1;
console.log(window.b) // undefined

不存在的变量提升

console.log(a); // undefined
var a = 1;

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

块级作用域

let a = 123;
{
    // console.log(a); // 暂时性死区导致代码报错
    let a = 234;
}
console.log(a);

虽然不存在变量提升的问题,但是如代码示例,由于大括号内声明了let,导致运行时出现ReferenceError错误。

那这不就是声明提前了么 ‍?

循环中的问题

for (let i = 0; i < 5; i++) {
  setTimeout(function(){
      console.log(i);
  }, 1000)
}
// console.log(i); // ReferenceError
// 结果:0,1,2,3,4

在使用let进行循环时出现了我们想要的结果,为什么呢?

首先分析一下,由于 var 声明的 i 是全局的,这就导致每次循环 i 就被重新赋值,而根据事件循环相关知识我们知道 setTimeout 是在同步代码 for 循环之后才会执行,所以每次输出结果都是5。

而在使用 let 声明的 i 不再是全局的,只在循环体内有效,所以在循环体外引用肯定会报错。再则就是每次循环都类似于重新声明 i 的变量,所以在循环体内部能正常使用 i 并输出。

感觉循环语句可以理解为一个函数作为父作用域声明了 i ;而循环体内部通过 {} 形成一个单独的子作用域,可以使用或修改 i ,甚至可以重新定义 i

修改 i 的值:

// 修改了i的值导致循环次数变少
for (let i = 0; i < 5; i++){
    i++;
    console.log(i);
}

// 对比理解
function loop(){
    let i = 1;

    {
        // 块级作用域操作父作用域变量
        i++;
        console.log(i);
    }
}

重新定义 i :

// 输出hahhaha
for (let i = 0; i < 5; i++){
    let i = 'hahhaha'
    console.log(i);
}

// 对比理解
function loop(){
    let i = 1;

    {
        // 块级作用域当然可以重新定义i
        let i = 'hahhaha';
        console.log(i);
    }
}

ES6 const

const 用来声明一个只读常量,声明时必须赋值,且不能重新赋值,其他特效和 let 相似。

const 实质是保证变量指向的内存地址不变更。所以对于如数值、字符串等基本类型由于数据名和值直接存储在栈中,所以不能可变更。而对于复杂类型,由于栈中存储的是数据名和堆的地址,所以改变复杂类型的属性是允许的。

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

使用ES5创建一个不可改对象 freeze

const foo = Object.freeze({});

// 常规模式时,下面一行不起作用;
// 严格模式时,该行会报错
foo.prop = 123;

babel转换

letconst 会被编译成 var

临时死区特性消失

// 源码
console.log(a);
let a = 100;

// 编译结果
"use strict";
console.log(a);
var a = 100;

重复定义编译时会出错

解决了循环时引用问题

// 源码
for (let i = 0; i < 5; i++) {
  setTimeout(function(){
      console.log(i)
  })
}


// 编译结果
"use strict";
var _loop = function _loop(i) {
  setTimeout(function () {
    console.log(i);
  });
};

for (var i = 0; i < 5; i++) {
  _loop(i);
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

软件框架设计的艺术

软件框架设计的艺术

[捷] Jaroslav Tulach / 王磊、朱兴 / 人民邮电出版社 / 2011-3 / 75.00元

本书帮助你解决API 设计方面的问题,共分3 个部分,分别指出学习API 设计是需要进行科学的训练的、Java 语言在设计方面的理论及设计和维护API 时的常见情况,并提供了各种技巧来解决相应的问题。 本书作者是NetBeans 的创始人,也是NetBeans 项目最初的架构师。相信在API 设计中遇到问题时,本书将不可或缺。 本书适用于软件设计人员阅读。一起来看看 《软件框架设计的艺术》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

在线进制转换器
在线进制转换器

各进制数互转换器

SHA 加密
SHA 加密

SHA 加密工具