【ES6复习】let和const
栏目: JavaScript · 发布时间: 6年前
内容简介:在使用虽然不存在变量提升的问题,但是如代码示例,由于大括号内声明了let,导致运行时出现ReferenceError错误。
let
和 const
作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转换
let
和 const
会被编译成 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); }
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。