其他章节请看:

es6 快速入门 系列

变量声明:let和const

试图解决的问题

经典的 var 声明让人迷惑

function demo1(v){
if(v){
var color='red'
}
console.log(color)
}
demo(1) // red

js引擎会将上面的 demo1 函数修改成下面的样子:

function demo2(v){
var color;
if(v){
color='red'
}
...
}

解决方法

var 声明改为 let 声明

function demo3(v){
if(v){
let color='red'
}
// 变量color在此处不存在
console.log(color)
} demo3(1) // 报错

let声明的用法与var相同。用 let 代替 var 来声明变量,就可以把当前作用域限制在当前代码块(指块级作用域)中。由于 let 声明不会被提升,因此开发者通常将 let 声明语句放在代码块顶部,以便整个代码块都可以访问

最佳实践

起初,对很多js开发者来说,let与他们实际想要的var一样,所以直接将var 替换成let。当更多的开发者迁移到es6后,另一种做法日益普及:默认使用const,只有确实需要改变变量的值才使用let,可能大部分的值在初始化后不会再改变。

补充

块级作用域

以前只有函数作用域,es6新增了块级作用域(字符{和}之间的区域)

// 函数作用域:变量i在函数demo4中有效
function demo4(){
if(true){
var i = 1
}
console.log(i) }
demo4() // 1
console.log(i) // 报错(i没有定义)
// 块级作用域:变量i只在if中的{和}之间有效
function demo5(){
if(true){
let i = 1
}
console.log(i) }
demo5() // 报错(i没有定义)

禁止重复声明

假设作用域中存在某变量(i),此时再用 letconst 关键字声明变量(i),就会抛出错误

var a = 1;
// 重复声明,抛出语法错误
let a = 1;
var a = 1;
if(1){
// 不会抛出错误(没有重复声明)
let a = 1;
}

const声明

es6提供 const 关键字来声明常量

常量必须一开始就初始化

// 正确
const i = 1
// 报错(常量未初始化)
const j;

不可以为 const 定义的常量再赋值(但允许修改值)

// 报错
const i = 1;
i = 2;
const obj = {}
// 正确(允许修改值)
obj.i = 1
// 错误(不允许修改绑定)
obj = {}

临时死区

用 let 或 const 声明的变量,会先存放在临时死区(TDZ)中,只有执行过变量声明语句后,变量才从TDZ中移除

if(true){
// 报错(访问临时死区中的变量,会报错)
console.log(typeof i)
let i = 1
}

循环中的块作用域绑定

var 声明让开发者创建函数非常困难

var funArr = []

for(var i = 0; i < 5; i++){
funArr.push(function(){
console.log(i)
})
} funArr[0]() // 5
funArr[1]() // 5

我们的预期是输出0~4,这里却全部输出5

可以用立即调用函数表达式(IIFE)来达到目的,就像这样:

var funArr = []

for(var i = 0; i < 5; i++){
funArr.push(function(i){
return function(){
console.log(i)
}
}(i))
} funArr[0]() // 0
funArr[1]() // 1

但我们可以用更简单的方式:循环中用 let 声明


var funArr = []
// 循环中用let声明:var 改用 let声明
for(let i = 0; i < 5; i++){
// let声明模仿上述例子中 IIFE 所做的一切(每次循环都创建一个新变量i,给新变量i赋值),
// 现在彻底删除 IIFE 之后仍可得到预期的结果
funArr.push(function(){
console.log(i)
})
} funArr[0]() // 0
funArr[1]() // 1

注:let声明在循环内部的行为是标准中专门定义的,不一定与 let 的不提升特性相关

全局块作用域绑定

var 声明的变量,会覆盖已存在的全局属性;let 和 const 声明的变量不会覆盖全局属性

// 覆盖全局属性RegExp
var RegExp = 'hello'
console.log(window.RegExp) // hello
let RegExp = 'hello'
console.log(window.RegExp) // RegExp() { [native code] }
console.log(RegExp) // hello

其他章节请看:

es6 快速入门 系列

es6 快速入门 系列 —— 变量声明:let和const的更多相关文章

  1. es6 快速入门 系列 —— 类 (class)

    其他章节请看: es6 快速入门 系列 类 类(class)是 javascript 新特性的一个重要组成部分,这一特性提供了一种更简洁的语法和更好的功能,可以让你通过一个安全.一致的方式来自定义对象 ...

  2. es6快速入门 系列 - async

    其他章节请看: es6 快速入门 系列 async 前文我们已经知道 promise 是一种异步编程的选择.而 async 是一种用于执行异步任务更简单的语法. Tip:建议学完 Promise 在看 ...

  3. es6 快速入门 系列 —— promise

    其他章节请看: es6 快速入门 系列 Promise Promise 是一种异步编程的选择 初步认识Promise 用 Promise 来实现这样一个功能:发送一个 ajax,返回后输出 json ...

  4. es6 快速入门 系列 —— 对象

    其他章节请看: es6 快速入门 系列 对象 试图解决的问题 写法繁杂 属性初始值需要重复写 function createPeople(name, age){ // name 和 age 都写了 2 ...

  5. es6 快速入门 系列

    es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...

  6. es6 快速入门 —— 函数

    其他章节请看: es6 快速入门 系列 函数 函数是所有编程语言的重要组成部分,es6之前函数语法一直没什么变化,遗留了许多问题,javaScript开发者多年来不断抱怨,es6终于决定大力度更新函数 ...

  7. python 全栈开发,Day88(csrf_exempt,ES6 快速入门,Vue)

    BBS项目内容回顾 1. 登陆页面 1. 验证码 1. PIL(Pillow) 2. io 2. ORM 1. 增删改查 3. AJAX $.ajax({ url: '', type: '', dat ...

  8. ES6快速入门(二)数据结构

    ES6快速入门 一.解构 1. 对象解构 let person = { name: 'Tang', age: 28 }; //必须同名,必须初始化 let {name, age} = person; ...

  9. ES6快速入门(一)函数与作用域

    ES6快速入门 一.块级绑定 1.var声明与变量提升 使用var声明的变量,不论在何处都会被视为(声明)在函数级作用域顶部的位置发生. function getValue(condition) { ...

随机推荐

  1. 1151 LCA in a Binary Tree

    The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...

  2. Codeforces Round #664 (Div. 2) C. Boboniu and Bit Operations

    传送门:cf1395C 题意 c[i]=a[i]&b[j],b[j]是b数组中任意一个,求c[1] | c[2] | ... | c[n]最小值. 题解 经典的二进制枚举答案,因为a和b的最大 ...

  3. 【uva 1151】Buy or Build(图论--最小生成树+二进制枚举状态)

    题意:平面上有N个点(1≤N≤1000),若要新建边,费用是2点的欧几里德距离的平方.另外还有Q个套餐,每个套餐里的点互相联通,总费用为Ci.问让所有N个点连通的最小费用.(2组数据的输出之间要求有换 ...

  4. 二叉排序树的构造 && 二叉树的先序、中序、后序遍历 && 树的括号表示规则

    二叉排序树的中序遍历就是按照关键字的从小到大顺序输出(先序和后序可没有这个顺序) 一.以序列 6 8 5 7 9 3构建二叉排序树: 二叉排序树就是中序遍历之后是有序的: 构造二叉排序树步骤如下: 插 ...

  5. Windows Server 2016 开启远程连接并延长过期时间

    按照下面文章配置,做完1.2步即可,其中协议号码填写 4954438 亲测有效! Server 2016默认远程桌面连接数是2个用户,如果多余两个用户进行远程桌面连接时,系统就会提示超过连接数,可以通 ...

  6. Python+Appium实现自动抢微信红包

    前言 过年的时候总是少不了红包,不知从何时开始微信红包横空出世,对于网速和手速慢的人只能在一旁观望,做为python的学习者就是要运用编程解决生活和工作上的事情. 于是我用python解决我们的手速问 ...

  7. conda 命令笔记

    1.虚拟环境 conda -V # 查看当前conda 版本 conda update conda # 更新conda conda env list 查看当前已有的虚拟环境 conda create ...

  8. USB2.0协议学习笔记---基本概念

    概念  USB是一种串行通信总线(Universal Serial Bus),经历的版本有USB1.0,USB1.1.USB2.0等.USB是一种主从模式的结构,因此它无法在设备与设备.主机与主机之间 ...

  9. 对于maven中无法加载类路径下的配置文件

    <build> <resources> <resource> <directory>src/main/java</directory> &l ...

  10. RT-Thread学习笔记1-启动顺序与线程创建

    目录 1. 启动顺序 2. 堆范围 3. 线程创建 3.1 线程代码(入口函数) 3.2 线程控制块 3.3 线程栈 4. 系统滴答时钟 5. GPIO驱动架构操作IO 6. 线程优先级 & ...