var
var是es5中声明变量的方式,它无需声明数据类型,而是根据所赋值的数据类型而改变自己的数据类型(重复声明不同的数据类型也可以改变原变量的数据类型),通过var声明的变量可以具有全局、方法作用域,并且var关键字会提升,即可以声明前调用
下面通过代码可以更深入的理解
var a
console.log(a)
a = 1
console.log(a,"'s type is "+typeof(a))
//控制台输出
undefined
1 's type is number
/////////////////////////////////////////////////////////////////////////////////////////////
((b)=>{
console.log(b)
//由于var声明提升,相当于在第一行加了 var a ,a还没有被赋值,因此a 为undefined
})(b)
var b = 12
//控制台输出
undefined
/////////////////////////////////////////////////////////////////////////////////////////////
var c = 12;
((c)=>{
//传入的c实际上是参数c,因此函数内的c改变不影响外面c的值,这也体现了var的函数作用域
c = c + 1
console.log('c in function is '+c)
})(c)
console.log('c in global is '+c)
//控制台输出
c in function is 13
c in global is 12
/////////////////////////////////////////////////////////////////////////////////////////////
(()=>{
if(a==undefined){
var a = '由于变量声明提升而有了a这个变量,但是还没有赋值,因而进入该if语句,赋值后有了这句话'
}
console.log(a)
})()
//控制台输出
由于变量声明提升而有了a这个变量,但是还没有赋值,因而进入该if语句,赋值后有了这句话
但是由于var声明变量的特殊性,导致了很多情况下,习惯了强类型语言的我们在编写代码时总会出现变量污染、重复声明后不知情等等难以发现的错误,因此es6中引入了let、const,这两种变量都具有全局作用域、方法作用域、局部作用域,他们俩更加靠近了java、c这些语言的变量声明特点
let
let较之于var,多了局部作用域,变量声明也不会提升了,更加像java、c中的变量
console.log(a)
let a = 1
//无法通过,由于let没有变量声明提升,因此会报错
ReferenceError: Cannot access 'a' before initialization
/////////////////////////////////////////////////////////////////////////////////////////////
(()=>{
if(true){
let a = 123123
console.log(a)
}
// 由于let由局部作用域,因此if语句外访问不到a
console.log(a)
})()
//控制台输出
123123
console.log(a)
^
ReferenceError: a is not defined
const
和let类似,但是const声明的是常量,不可被重新赋值,但是可以正常修改常量中的变量
const a =1
a = 2
//控制台输出
a = 2
^
TypeError: Assignment to constant variable.
/////////////////////////////////////////////////////////////////////////////////////////////
const b = {
name:'tom'
}
b = {
name:'RUIENGER'
}//执行到这里报错,因为不能给b重新赋值
//将上面三行注释后,可以通过,并且name为RUIENGER,说明可以正常访问、修改常量里面的变量
b.name = 'RUIENGER'
console.log(b)
//注释后控制台输出
{ name: 'RUIENGER' }