【ES6复习】let和const
栏目: JavaScript · 发布时间: 7年前
内容简介:在使用虽然不存在变量提升的问题,但是如代码示例,由于大括号内声明了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);
}
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Visual C#从入门到精通(第8版)
夏普 (John Sharp) / 周靖 / 清华大学出版社 / 2016-6-1
《Visual C#从入门到精通(第8版)》共27章,结构清晰,叙述清楚。所有练习均在Visual Studio 2015简体中文版上进行过全面演练。无论是刚开始接触面向对象编程的新手,还是打算迁移到C#的C、C++或Java程序员,都可以从《Visual C#从入门到精通(第8版)》汲取到新的知识。迅速掌握C#编程技术。一起来看看 《Visual C#从入门到精通(第8版)》 这本书的介绍吧!