var
在ES5中,顶层对象的属性和全局变量是等价的,用var声明的变量既是全局变量也是顶级变量,顶级变量在浏览器上指的是window对象,在node中指的是global对象
var a = 10
console.log(a) // 10
-
使用var声明的变量存在变量提升的情况
console.log(a) // undefined
var a = 20
在编译阶段,编译器会将代码变成以下执行
var a;
console.log(a)
a=20
-
使用var,可以对一个变量多次进行声明,后面声明的变量的值会覆盖前面声明的
var a = 10
var a = 20
console.log(a) // 20
-
在函数使用var声明的变量,该变量是局部变量
var a = 20
function fn() {
vae a = 30
}
fn()
console.log(a) // 20
-
而如果在函数内不使用var,该变量是全局的
var a = 20
function fn () {
a = 30
}
console.log(a) //30
let
let是ES6新增的命令,用来声明变量
用法和var相似,但是所声明的变量,只在let命令所在的代码块有效
-
块级作用域
{
let a = 20
}
console.log(a) //ReferenceError: a is not defined.
-
没有变量的提升
console.log(a) // 报错ReferenceError
let a = 2
这表示在声明它之前,变量 a 是不存在的,这时如果⽤到它,就会抛出⼀个错误
只要块级作⽤域内存在 let 命令,这个区域就不再受外部影响
var a = 123
if(true) {
a='abc' //ReferenceError
let a;
}
使⽤ let 声明变量前,该变量都不可⽤,也就是⼤家常说的“暂时性死区”
-
let不允许在相同的作用域中重复声明
let a = 20
let a = 30
// Uncaught SyntaxError: Identifier 'a' has already been declared
const
-
const声明一个只读的常量,一旦声明,常量的值不能修改
const a = 5
a = 8
// TypeError: Assignment to constant variable
-
这就意味着,常量一旦声明变量,就必须立即初始化,不能留到以后赋值
const a;
// SyntaxError: Missing initializer in const declaration
-
如果之前使用var或者let声明过的变量,再用const声明同样会报错
var a = 20
let b = 20
const a = 30
const b = 30
// 都会报错
const 实际上保证的并不是变量的值不得改动,⽽是变量指向的那个内存地址所保存的数据不得改动 对于简单类型的数据,值就保存在变量指向的那个内存地址,因此等同于常量 对于复杂类型的数据,变量指向的内存地址,保存的只是⼀个指向实际数据的指针, const 只能保证这 个指针是固定的,并不能确保改变量的结构不变
const foo = {};
// 为 foo 添加⼀个属性,可以成功
foo.prop = 123;
foo.prop // 123
// 将 foo 指向另⼀个对象,就会报错
foo = {}; // TypeError: "foo" is read-only
其他情况,const与let一致
区别
var 、 let 、 const 三者区别可以围绕下⾯五点展开:
-
变量提升
-
暂时性死区
-
块级作用域
-
重复声明
-
修改声明的变量
-
使用
变量提升
var 声明的变量存在变量提升,即变量可以在声明之前调⽤,值为 undefined let 和 const 不存在变量提升,即它们所声明的变量⼀定要在声明后使⽤,否则报错
暂时性死区
var 不存在暂时性死区 let 和 const 存在暂时性死区,只有等到声明变量的那⼀⾏代码出现,才可以获取和使⽤该变量
块级作用域
var 不存在块级作⽤域 let 和 const 存在块级作⽤域
重复声明
var 允许重复声明变量 let 和 const 在同⼀作⽤域不允许重复声明变量
修改声明的变量
var 和 let 可以 const 声明⼀个只读的常量。⼀旦声明,常量的值就不能改变
使用
能⽤ const 的情况尽量使⽤ const ,其他情况下⼤多数使⽤ let ,避免使⽤ var