当前位置:网站首页>let const
let const
2022-07-07 05:56:00 【lazytomato】
start
- 我又来学习ES6了。
- 因为我发现我在使用某些ES6的 API的时候,总觉得差点意思。
- 花点时间,结合思维导图的形式,系统性的过一遍。
- ღ( ´・ᴗ・` )比心
思维导图:
1. let 和 const 有哪些特点(相同点)
1.1 不会变量提升
console.log(lazy) // undefined
var lazy= '偷懒'
console.log(tomato) // tomato is not defined
let tomato= '你好呀'
讨论
var a = 1
function s() {
console.log(a)
let a = 2
// 如果不写 `let a = 2` 上面的console.log(a) 会打印 1
// 但是写了 `let a = 2` Cannot access 'a' before initialization
}
s()
如何解释上面的代码
变量提升只是一种语法定义。
其实实质就是一段代码在上下文创建阶段(也就是编译阶段)是能够识别到 var 和 let 创建的变量的
只会对二者的操作不一样:对 var 定义的变量初始化为 undefined,而 let 定义的变量仍然处于未初始化状态。
1.2 重复声明报错
代码
var a = '1'
console.log(a)
var a = '2'
console.log(a)
let b = '1'
console.log(b)
let b = '2' // Uncaught SyntaxError:Identifier 'b' has already been declared 翻译一下:未命名 语法错误: 标识符“b”已声明
console.log(b)
思考
- 使用 let 去声明两次同一个名称的变量,直接报错了,整体代码都不运行了。(运行效果可以看后续截图)
- 分开运行上下两块代码,var 是支持重复声明的。
运行截图
1.3 不绑定全局作用域
代码
var a = '1'
let b = '2'
console.log(window.a) // 1
console.log(window.b) // undefined
解释
顶层对象的属性与全局变量挂钩,被认为是 JavaScript 语言最大的设计败笔之一。这样的设计带来了几个很大的问题,首先是没法在编译时就报出变量未声明的错误,只有运行时才能知道(因为全局变量可能是顶层对象的属性创造的,而属性的创造是动态的);其次,程序员很容易不知不觉地就创建了全局变量(比如打字出错);最后,顶层对象的属性是到处可以读写的,这非常不利于模块化编程。另一方面,window
对象有实体含义,指的是浏览器的窗口对象,顶层对象是一个有实体含义的对象,也是不合适的。
ES6 为了改变这一点,一方面规定,为了保持兼容性,var
命令和function
命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let
命令、const
命令、class
命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩
-内容来自 ECMAScript 6 入门教程_阮一峰
个人思考
对于我自己来说,这个地方是一个很模糊的点。了解到 顶层对象的属性与全局变量挂钩 的缺点后,这样做的原因还是很好理解的。
小记一下: let
命令、const
命令、class
命令声明的全局变量,不属于顶层对象的属性
1.4 暂时性死区
代码
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError: Cannot access 'tmp' before initialization 翻译一下 引用错误: 在初始化之前无法访问 'tmp‘
let tmp;
}
思考
只要块级作用域内存在
let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。在代码块内,使用
let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
1.5 块级作用域
先看代码
代码1
if (false) {
var a = 1
}
console.log(a) // undefined
console.log(b) // ReferenceError: b is not defined
代码2
let a = 1
{
let b = 2
}
console.log(a) // 1
console.log(b) // ReferenceError: b is not defined
思考
- ES5 只有全局作用域和函数作用域,没有块级作用域。这就会导致 代码1 中的
var a
会被提升到顶部。 - 而 let const 声明的是存在块级作用域的,在外部是无法读取的。
块级作用域
MND的官方说明:块作用域
任何一对花括号 {} 中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
总结
- ES5 只有全局作用域和函数作用域,没有块级作用域。
- ES6 的块级作用域必须有大括号,如果没有大括号,JavaScript 引擎就认为不存在块级作用域。
我理解到的是,ES6中主要注意 if 和 trycatch 的大括号,会有块级作用域。
2. 不同点
const声明的变量指向的那个内存地址所保存的数据不得改动。
推荐使用const声明变量,确保变量内存地址不变,可以减少bug的发生。
3. 扩展
3.1 函数能不能在块级作用域声明?
例如在 if
, trycatch
中声明函数。
ES5 规定,函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。
但是!! 浏览器没有遵守这个规定 还是支持在块级作用域之中声明函数。
ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。ES6 规定,块级作用域之中,函数声明语句的行为类似于
let
,在块级作用域之外不可引用。如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6 在附录 B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。
- 允许在块级作用域内声明函数。
- 函数声明类似于
var
,即会提升到全局作用域或函数作用域的头部。 - 同时,函数声明还会提升到所在的块级作用域的头部。
注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作
let
处理。
看的稍微有点绕,我多读了几遍,写一写自己的理解。
ES5中是不允许块级作用域声明函数的,但是浏览器中是支持的。
ES6中明确允许的块级作用域可以声明函数,但是在块级作用域中,函数声明语句类似 let。外部不可引用。
为了减少 ES6 的改动对 ES5的影响,对浏览器的实现,可以不按照 ES6规定实现,按如下规定实现:
允许在块级作用域内声明函数。
函数声明类似于
var
,即会提升到全局作用域或函数作用域的头部。同时,函数声明还会提升到所在的块级作用域的头部。
#以上三条仅针对 ES6的浏览器 实现有效。
3.2 顶层对象
浏览器里面,顶层对象是window,但 Node 和 Web Worker 没有window。
浏览器和 Web Worker 里面,self也指向顶层对象,但是 Node 没有self。
Node 里面,顶层对象是global,但其他环境都不支持。
3.3 ES6 声明变量的六种方法
ES5 只有两种声明变量的方法:
var
命令和function
命令。ES6 除了添加
let
和const
命令,还有两种声明变量的方法:import
命令和class
命令。所以,ES6 一共有 6 种声明变量的方法。
end
其实这是我第三次学这个 let 和 const 了,可能不是最后一次。
当然这次也是很有收获,例如:
块级作用域;
函数在块级作用域的声明;
let const 到底会不会变量提升;
其次 let const 的新特性,都是用来解决以前的痛点和问题点,知道原因再看结果就很通透了。
编写于2022/07/06-23/10
边栏推荐
- You should use Google related products with caution
- Opencv learning note 5 - gradient calculation / edge detection
- [kuangbin]专题十五 数位DP
- Openvscode cloud ide joins rainbow integrated development system
- 南京商品房买卖启用电子合同,君子签助力房屋交易在线网签备案
- Famine cloud service management script
- A method for quickly viewing pod logs under frequent tests (grep awk xargs kuberctl)
- 数据库存储---表分区
- One click deployment of highly available emqx clusters in rainbow
- AVL balanced binary search tree
猜你喜欢
In go language, function is a type
IP地址的类别
2 - 3 arbre de recherche
Splunk中single value视图使用将数值替换为文字
The single value view in Splunk uses to replace numeric values with text
Data type - integer (C language)
Fluentd is easy to use. Combined with the rainbow plug-in market, log collection is faster
Train your dataset with swinunet
Pvtv2--pyramid vision transformer V2 learning notes
[Yu Yue education] higher vocational English reference materials of Nanjing Polytechnic University
随机推荐
XCiT学习笔记
iptables 之 state模块(ftp服务练习)
A method for quickly viewing pod logs under frequent tests (grep awk xargs kuberctl)
Golang 编译约束/条件编译 ( // +build <tags> )
21 general principles of wiring in circuit board design_ Provided by Chengdu circuit board design
POJ - 3616 Milking Time(DP+LIS)
PVTV2--Pyramid Vision TransformerV2学习笔记
[Chongqing Guangdong education] audio visual language reference materials of Xinyang Normal University
Data type - integer (C language)
[paper reading] icml2020: can autonomous vehicles identify, recover from, and adapt to distribution shifts?
Splunk query CSV lookup table data dynamic query
The single value view in Splunk uses to replace numeric values with text
Opencv learning notes 1 -- several methods of reading images
[Chongqing Guangdong education] accounting reference materials of Nanjing University of Information Engineering
Componentspace2022, assertions, protocols, bindings, and configuration files
[Yu Yue education] higher vocational English reference materials of Nanjing Polytechnic University
关于基于kangle和EP面板使用CDN
DeiT学习笔记
Required String parameter ‘XXX‘ is not present
[kuangbin] topic 15 digit DP