var&let&const的区别
变量提升
var声明的变量会发生“变量提升”,即在变量没有声明之前就调用该变量
console.log(aimer) // undefined
var aimer = "march of time"
之所以会造成变量提升是因为在执行JS代码之前浏览器会对JS代码进行预解析,将var声明的变量 以及function函数提升到顶部,上面代码经过预解析之后是这样
var aimer
console.log(aimer)
aimer = "march of time"
而 let const则不会发生"变量提升"
console.log(aimer) // Cannot access 'aimer' before initialization
let aimer ="march of time"
console.log(aimer) // Cannot access 'aimer' before initialization
const aimer ="march of time"
块级作用域
var声明的变量只有函数作用域和全局作用域 不具备块级作用域,例如喜闻乐见的面试题,点击当前的li拿到当前的索引!
<ul>
<li>0</li> //5
<li>1</li> //5
<li>2</li> //5
<li>3</li> //5
<li>4</li> //5
</ul>
let lis = document.querySelectorAll('li')
for (var i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
console.log(i)
}
}
上面代码无论点击哪一个打印的都会是5,因为for循环是同步而点击事件是异步,在点击之前循环已经结束.尽管每一次循环声明的变量值都自增1,但因为没有块级作用域(for循环用var声明的变量会泄漏为全局变量)并没有有效的保存那些变量值,导致点击任何一个li得到的都是lis的最大长度。
<ul>
<li>0</li> //0
<li>1</li> //1
<li>2</li> //2
<li>3</li> //3
<li>4</li> //4
</ul>
let lis = document.querySelectorAll('li')
for (let i = 0; i < lis.length; i++) {
lis[i].onclick = function () {
console.log(i)
}
}
而使用let来声明则可以避免这种奇怪的现象,let声明的变量具有块级作用域,每次循环都创建了一个块级作用域来保存当前的变量.确保每次拿到的变量和之前的值不一样!
不允许重复声明
在同一个作用域下用let重复声明变量会报错,var重复声明不会报错
// 报错
function aimer() {
let aimer = 30
var aimer = 20
}
// 不报错
function aimer() {
var aimer = 30
var aimer = 20
}
暂时性死区(TDZ)
ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
if (true) {
aimer = 're:pary' //报错
console.log(aimer) // 报错
let aimer
}
const指令
const和let有许多共同之处(块级作用域 暂时性死区 不可重复声明 不具备变量提升 ),但也有些细微的不同.
- const定义的常量必须马上赋值否则会报错 let不会
const aimer // 报错
let aimer // 不报错
- const声明的是只读的常量 不可更改
尽管const声明的常量不可更改,但实际上保证的常量的内存地址不能更改,如果const声明的是数组或者对象,在不修改内存地址的前提下依然可以修改里面的属性
const aimer = { sing: 'march of time' }
aimer.age = 29
console.log(aimer) // sing:'march of time' age:29
const aimer = ['Tone']
aimer.push('Lris')
console.log(aimer) // [Tone Lris]
如果要让const定义的常量完全不能更改也可以通过Object.freeze来冻结那些属性或者利用Object.defineProperty里面的writable属性来控制是否可以修改
const aimer = { sing: 'Tone' }
Object.freeze(aimer)
aimer.sing = 'Save'
console.log(aimer) // {sing:'Tone'}
const aimer = { sing: 'Tone' }
Object.defineProperty(aimer, 'sing', {
writable: false
})
aimer.sing = 'Save'
console.log(aimer) // {sing:'Tone'}
总结
- var 具有变量提升 let const没有
- var 没有块级作用域 let const有
- var 在同一个作用域下可以反复声明 let const不行
- let const 有暂时性死区 var没有
- let const 必须先定义在使用否则报错 var不会
以上是个人对var let const的理解如有错误欢迎指正