var命令
var
声明的变量具有变量提升;
console.log(a); // undefined
var a = '变量提升';
/*
实则运行过程:
var a;
console.log(a);
a = '变量提升';
*/
var
没有块级作用域;
{
var a = '无块级作用域';
}
console.log(a); // '无块级作用域'
-
var
声明的变量挂载于何处;
1.在全局执行上下文中用var
声明的变量,一份存储在全局作用域(充当全局变量),另一份存储于全局对象window属性下。故:var a = '1'; console.log(a); // '1' console.log(window.a); // '1' /* 注意: 如果a变量没有声明定义 console.log(a); //报错:a is not defined console.log(window.a); // undefined */
2.在函数执行上下中用
var
声明的变量,因为函数存在作用域,所以变量只存在于该函数作用域里,只能函数里访问该变量并且变量不会绑定在全局变量window对象下。函数执行完,自动释放该变量,等待浏览器回收整理内存空间。注意:如果是闭包,那么该变量不会自动释放,一直存在(当然可以手动释放)。 -
var
声明的变量名可以重复(同一作用域或同一执行上下文中);
var a = 1;
var a = 2;
console.log(a); // 2
let命令
let
不存在变量提升;
console.log(a); // 报错:a is not defined
let a = 1;
let
存在块级作用域;
{
let a = 1;
}
console.log(a); // 报错:a is not defined
-
let
声明的变量挂载于何处;
1.全局执行上下文中:只会充当全局变量,并不会在window
对象下挂载这个变量属性,区别于var
在全局执行上下文中声明的变量;let a = '全局变量'; console.log(a); // '全局变量' console.log(window.a); // undefined
2.函数执行上下文中:使用情形与var相同(因为函数存在作用域,所以变量只存在于该函数作用域里,只能函数里访问该变量。函数执行完,自动释放该变量,等待浏览器回收整理内存空间。注意:如果是闭包,那么该变量不会自动释放,一直存在。);
-
let
声明的变量名不可以重复(同一作用域或同一执行上下文中);
let b = 1;
let b = 2; // Uncaught SyntaxError: Identifier 'b' has already been declared
let
在块级作用域里存在’暂时性死区‘;
var tmp = 123;
if (true) {
tmp = 'abc'; // ReferenceError
let tmp;
}
const命令
- 不存在变量提升;
- 存在块级作用域(与let一样);
- 声明的变量挂载于何处(与上述
let
相同); - 声明的变量名不可以重复(同一作用域或同一执行上下文中);
- 声明的变量名所对应的变量值是不能改变的(变量值为基本数据类型和引用数据类型都是不可以改变);
const a = 1;
const obj = {age: 18};
a = 2; // 报错
obj = {age: 18, name: '阿童木'}; // 报错
// 注意:当变量值为引用数据类型时,变量名所对应的地址值是不能改变的,但是对象的属性和方法是可以进行增删改操作的;
const objPro = {age: 18};
Reflect.set(objPro, 'name', '阿童木1号'); // 增
Reflect.set(objPro, 'name', '阿童木2号'); // 改
Reflect.deleteProperty(objPro, age); // 删
- 对于用
let
和const
都可以声明定义的变量,建议使用const;
let a = 1;
let obj = {};
/*
a变量和obj变量的变量值之后都不会改变(常量),建议使用如下const声明定义,使用const的优点有:1.看到const定义变量,就顾名思义这个变量是常量,不能更改;2.符合函数式编程思想;3.JavaScript 编译器会对const进行优化这一个机制;
*/
const A = 1;
const OBJ = {};
总结:let
命令完全取代var
命令,能用let
和const
声明定义的变量,使用const
声明定义;