话不多说,直接上干活,我们先来说说一直存在并使用的 var,虽然现在有let和const了,但还是有很多人在使用它

一、 var

1. 使用var声明的变量它并不属于一个块作用域的变量,它属于函数域变量
1
2
3
4
5
6
7
8
9
10
11
12
13
 //代码一
function test() {
console.log(age);
var age = 26;
}
test(); // undefined
//没报错是因为上面的被浏览器运行时看做等价于下面的代码
function test() {
var age;
console.log(age);
age = 26;
}
test() //undefined
2. 变量可重复声明

多次声明只算最后一次有效,因为var声明后的变量会提升,所以重复声明一个变量会合并成一个声明的变量

1
2
3
4
5
6
7
8
9
function test() {
var age = 10;
age = 20,
age = 30,
age = 40,
console.log(age);
}
test()//40

3. 全局声明挂载window

全局声明会挂载到window上面,成为window的一个属性

1
2
var test = 10
console.log(window.test); //10
4. 循环声明

循环迭代定义的变量会在循环结束时,渗透到循环的外部

1
2
3
4
for(var i = 0;i < =5;i++){
//循环逻辑
}
console.log(i); //5

二、 let

1. 使用let声明的变量它属于一个块作用域的变量
1
2
3
4
5
6
 //代码一
function test() {
console.log(age);
let age = 26;
}
test(); // 报错,age 未定义
2. 变量不可重复声明
1
2
3
4
5
6
7
8
function test() {
let age = 10;
age = 20,
age = 30,
console.log(age);
}
test() //报错,age 已声明过,不可重复声明

3. 全局声明不挂载window

全局声明不挂载window上面,也不会成为window的一个属性,不过let声明的变量仍然是存在于全局作用域中,声明的相应变量会保存在页面的声明周期内存中。因此,为了避免 SyntaxError,必须确保页面中不会重复声明同一个变量

1
2
let test = 10
console.log(window.test); //undefined
4. 循环声明

循环迭代定义的变量不会在循环结束时,渗透到循环的外部,仅限在for循环中使用,因为let声明的变量属于 块级作用域

1
2
3
4
for(let i = 0;i < =5;i++){
//循环逻辑
}
console.log(i); // i 未定义

三、const

1. 声明行为

const声明和let声明的行为大同小异,不同之处在于,const声明变量的同时必须初始化变量(赋予一个有效值),并且在程序运行时修改这个变量的时候会导致程序运行错误。const声明的变量属于常量

1
2
const age = 30
age = 45//TypeError: 给常量赋值
2. const 的作用域

const属于块级作用域,和let一样,同样也不可重复声明变量

1
2
const age = 30
const age = 20//SynTaxError 重复声明
3. const 声明变量的修改

const声明变量的限制只限制于它声明时指向的变量的引用。换句话说,如果const声明的是一个对象,而你修改对象里的属性并不会违背const的限制

1
2
3
4
5
6
7
const person = {
name: "张三"
}
console.log(person.name); // 张三
//修改
person.name = "李四"
console.log(person.name); // 李四
3. for 循环中 const

虽然constlet很相似,但还是不能用const声明,因为迭代变量会自增

1
2
3
4
5
6
7
//错误代码
for(const i = 0;i < 5;i++){}//TypeError 给常量赋值
//正确代码
let i = 0
for(const j = 7;i < 5;i++){
console.log(j)
}//7,7,7,7,7

如果说你还是想用const ** 声明,你可以像下面这样做,但只对for-infor-of**有效

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//代码一
const person = {
a: 1,
b: 2
}
for(const key in person){
console.log(key)
}
// a,b
//代码二
const arr = [1,2,3]
for(const item of arr){
console.log(item)
}
// 1,2,3

四、总结

  1. var声明属于函数作用域,会提升到函数作用域的顶部
  2. let 声明属于块级作用域,不会提升到函数作用域的顶部,在未声明前调用需要声明的变量会报错(xxx未定义)
  3. for循环中使用var声明会在for循环结束时渗透到外部,而使用let声明则不会出现这种情况
  4. const声明的变量属于常量,不可对其进行直接进行更改,可对其属性进行修改
  5. constlet一样属于块级作用域的声明,并且都不能重复声明

五、使用建议

1. 不使用 var

有了constlet后,可以替代var,因为constlet没有var的那些副作用,constlet有自己的作用域,使用constlet久了你会发现自己的代码质量有了提升

2. const 优先原则,let 次之

使用const声明可以让浏览器运行时强制保持变量不变,也可以让静态代码分析工具,提前发现不合法的赋值操作。因此,应该优先使用const来声明变量,只在提前知道未来会有修改时,再使用let。这样可以推断某些变量的值永远不会变,同时也能迅速发现因意外赋值导致的非预期行为。

下期预告

JavaSript的数据类型