let和const作为新的定义变量的方式,解决了var定义变量存在的一些问题。
但是前些天同时问我 const 定义的变量可不可更改,我只知道我们通常不会更改,但是其实也不是的。
某些情况还是可以更改的,于是我打算对这些情况一探究竟。
话不多说,我们开始吧。
首先,var定义变量存在的问题主要是
- 变量声明提升
- JS没有块级作用域
- 循环内变量过度共享,代码如下
1
2
3
4
5
6for (var i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i)
}, 1000);
}
// 控制台输出了3个3
下面依次介绍let和const
let
let声明的变量拥有块级作用域
1
2
3
4
5
6
7
8for(var i=0;i<10;i++){
var a = 'a'
}
for(var i=0;i<10;i++){
let b = 'b'
}
console.log(a) // a
console.log(b) // Uncaught ReferenceError: b is not definedlet声明的全局变量不是全局对象的属性
这就意味着,你不可以通过window.变量名的方式访问这些变量。它们只存在于一个不可见的块的作用域中,这个块理论上是Web页面中运行的所有JS代码的外层块。1
2
3
4var c = 'c'
let d = 'd'
console.log(window.c) //c
console.log(window.d) //undefined形如for (let x…)的循环在每次迭代时都为x创建新的绑定
正因为let声明的变量不在全局中,而在一个不可见的作用域中。
所以,如果for循环执行多次并且循环保持了一个闭包,那么每个闭包将捕捉一个循环变量的不同值作为副本,而不是所有闭包都捕捉循环变量的同一个值。1
2
3
4
5
6for (let i = 0; i < 3; i++) {
setTimeout(function () {
console.log(i)
}, 1000)
}
// 控制台输出1 2 3
这种情况适用于现有的三种循环方式:for-of、for-in、以及传统的用分号分隔的类C循环
- 用let重定义变量会抛出一个语法错误(SyntaxError)
1
2let a = 'a'
let a = 'b' // Uncaught SyntaxError:Identifier 'a' has already been declared
在这些不同之外,let和var几乎很相似了。举个例子,它们都支持使用逗号分隔声明多重变量,它们也都支持解构特性。
const
一句话说明白,const 就是用来定义常量的!任何非主流的写法都是非法的
比如这样:
1 | //只声明变量不赋值 |
这样
1 | //重复声明变量 |
还有这样
1 | //给变量重新赋值 |
最后是经常容易忽略的特殊情况,看似黑科技
1 | //不过不推荐这么干,实在没啥意思,常量常量,不变的才叫常量嘛~ |
其实不是黑科技
1 | const a = {a:'a'}; // 绑定的是对象指针 |
- 本文作者: Jambo
- 版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!