【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);
}

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

查看所有标签

猜你喜欢:

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

Numerical Recipes 3rd Edition

Numerical Recipes 3rd Edition

William H. Press、Saul A. Teukolsky、William T. Vetterling、Brian P. Flannery / Cambridge University Press / 2007-9-6 / GBP 64.99

Do you want easy access to the latest methods in scientific computing? This greatly expanded third edition of Numerical Recipes has it, with wider coverage than ever before, many new, expanded and upd......一起来看看 《Numerical Recipes 3rd Edition》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

html转js在线工具
html转js在线工具

html转js在线工具