一、ES5 的 var
关键字
var
存在变量提升var
允许重复声明,浏览器本身只识别一次,但不会报错var
声明的变量即是全局变量,也相当于给GO(window)
设置了一个属性而且两者建立映射机制- 基于
typeof
检测一个没有被声明过的变量,并不会报错,结果是"undefined
";但是从正确的角度来讲应该报错才是正常的! var
没有块级作用域
二、 let
关键字
- 不会存在变量提升
- 必须先定义在使用,没有定义就使用的话就会报错
- 会产生作用域
- 和
const
一样不允许重复声明变量
console.log(a); // Cannot access 'a' before initialization ⇒ a 不能再初始化之前使用
let a = 10;
let a = 20;
console.log(a); // SyntaxError: Identifier 'a' has already been declared ⇒ 因为变量 a 已经被赋值了
function (num) {
let num; // 报错,不能在函数内部重新声明参数
console.log(num);
}
- 和
const
一样有暂时性死区(TDZ
) – 在声明变量之前, 该变量都不能使用
let a = 10;
console.log(a); // 10
let c = 10;
{
let c = 20;
console.log(c); // 20
}
{
let d = 2;
console.log(d); // 2
}
console.log(d); // d is not defined
// 只要块级作用于内存在let命令,他声明的变量就会"绑定"在这个区域,不会受外部的影响
var e = 2;
if (true) {
e = 1; // Cannot access 'e' before initialization
let e;
}
- let 声明的变量仅仅是全局变量,和
GO
没什么关系 - 如果这个变量在后面会用到
let
声明,则前面在基于typeof
检测就会报错:不能在声明之前使用
三、 const
关键字
- 用
const
关键字生命的变量叫常量(具有只读属性),常量的值不能被修改
const a = 10;
a = 20;
console.log(a); // 报错,常量不能被更改
- 用
const
声明变量要赋初值,不然会报错
const a;
a = 19;
console.log(a); // 会报错,常量必须初始化
-
const
声明的对象- 保存的是变量的地址不变,而不是变量的地址所对应的值不变
const
声明的对象,存的是一个地址,这个地址指向一个对象
const obj = {
name: '张三',
age: 19
}
obj.age = 20; // 可以用对象的属性或者方法修对象的值
console.log(age); // 20
obj = { // 这里会报错,常量不能被更改
age = 17
}
console.log(obj.age);
const arr = [1, 2, 3, 4, 5];
arr.shift();
console.log(arr); // 2, 3, 4, 5;
四、 object.freeze(a)
– 冻结数组,让 let
声明的东西也不可以被更改
let arr = [1, 2, 3]
let result = Object.freeze(arr); // 如果实在不想修改数组里面的值,可以把这个数组冻结了
result.push(4);
console.log(result); // 报错,因为对象已经被冻结了,不可以被扩展
五、小 tips
let
关键字 和const
关键字 立即执行函数,让整个代码更加符合模块化的规范- 作用域的产生和定义变量的方式有关
- 只要在{大括号}里面使用
let
或者const
定义变量,那么这个变量的作用范围就在这个括号内,不会存在变量提升,let
必须先声明后使用,const
在声明的时候必须赋初值
面试题
- 用
const
定义的变量值,永远不能被修改了?- 不对
1.const
不能更改指的是:这个变量不能再和其他值进行关联了,也就是不能修改const
声明变量的指向
2. 但是可以在不改变指向的情况下,修改堆内存中的信息(这样也算是把值更改了)
3. 所以:const
声明的变量,不能修改它的指向,但是可以改变其存储值