本文详细解析JavaScript中var与let声明变量的核心区别。重点涵盖作用域差异(函数作用域vs块级作用域)、变量提升机制以及暂时性死区现象,并通过代码示例说明它们在循环和重复声明中的不同表现,帮助开发者写出更规范的代码。
引言:
var是JavaScript在早期版本中即已具备的变量声明关键字,而let作为ES6规范引入的变量声明方式,二者之间存在显著差异。具体差异体现在哪些方面?
1.作用域范围存在差异
var具备函数级作用域,let具备块级作用域
{
var monkey='熏悟空';
let pig='猪扒盖';
}
console.log(monkey); //输出undefined
console.log(pig); //报错:pig is not deined
从上述代码可以看出,let所声明的变量仅在其所属的代码块内部有效,在代码块外部无法访问;而var声明的变量则在该代码块所属的整个函数作用域内均有效。
2.变量提升机制不同
var声明的变量会触发变量提升机制,而let声明的变量不会触发变量提升。
console.log(monkey); //undefined
var monkey='熏悟空';
console.log(pig); //报错:pig is not defined
let pig='猪扒盖';
基于相同逻辑,为何var声明的变量在声明前调用会返回未定义,而let声明的变量在声明前调用会抛出异常?这正是两者在变量提升机制上的区别:var存在变量提升,let不存在变量提升。
所谓变量提升,此处不作概念性定义,仅阐述个人理解:上述代码实际上等价于如下形式:
var monkey;
console.log(monkey); //undefined
monkey='熏悟空';
console.log(pig); //报错:pig is not defined
let pig='猪扒盖';
观察差异可知,var声明的变量会将声明语句提取至作用域顶部进行定义但不赋值,赋值操作仍保留在原代码位置。因此,当调用var声明的变量时,得到的是一个已声明但未赋值的变量,调用结果为undefined,此即变量提升现象。而let定义的变量不具备这种变量提升特性。
3.暂时性死区(TDZ)差异
暂时性死区:若在某一作用域内使用let声明变量,且外部作用域存在同名变量,则即便在内部作用域中修改该变量,也不会影响外部作用域。
具体表现如下:
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(i)
},1000)
}
for(let i=0;i<5;i++){
setTimeout(function(){
console.log(i)
},1000)
}
请问这两段代码的运行结果分别是什么?
第一段代码运行结束后,1秒后按顺序打印五个5;第二段代码运行结束后,1秒后按顺序打印0,1,2,3,4。
为何会产生这种差异?
因为第一段代码中的变量i由var关键字声明,不存在暂时性死区,即1秒后在setTimeout回调中访问到的变量i是全局上下文中for循环执行完毕后的最终值,因此打印结果全为5;
而第二段代码中的变量i由let关键字声明,触发了暂时性死区,setTimeout回调中的i变量保存的是每次循环迭代时的快照值,该快照值不会因外部存在同名且值不同的变量而改变,仍保持之前存储的值。这正是暂时性死区的体现,也是第二段代码运行后按顺序打印0,1,2,3,4的原因。
4.同一作用域内var允许重复声明,let不允许
let monkey='熏悟空';
let monkey='逼马吻'; //报错:Identifier 'a' has already been declared
var pig='猪扒盖';
var pig='猪肛裂'; //正常访问,变量pig的值被替换
至此,关于JavaScript中var与let区别的介绍到此结束,更多相关JavaScript知识请查阅本站往期文章或继续浏览下方相关文章,希望大家日后多多支持本站!