一、三者区别总结
区别 | var | let | const |
---|---|---|---|
是否有块级作用域 | × | ✔️ | ✔️ |
是否存在变量提升 | ✔️ | × | × |
是否添加全局属性 | ✔️ | × | × |
能否重复声明变量 | ✔️ | × | × |
是否存在暂时性死区 | × | ✔️ | ✔️ |
是否必须设置初始值 | × | × | ✔️ |
能否改变指针指向 | ✔️ | ✔️ | × |
(表格摘自优快云博主「前端编程之家」的原创文章,文章链接:https://blog.youkuaiyun.com/xiaoqingrong/article/details/119153274)
二、var
1.var声明的作用域
var声明的变量属于函数作用域。
//当var声明处于函数之外,表示声明对象为全局变量,如下
var a = 1;
//当声明变量处于函数之内,表示声明对象为此函数的局部变量,如下
function f1(){
var a = 2;
console.log(a);//输出2
}
console.log(a);//输出1
//当省略var去声明变量时,此变量为全局变量,如下
b = 1;
function f2(){
b = 2;
console.log(b);//输出2,更新b
}
console.log(b);//输出2
2.var的变量提升
var的声明会在js预解析时把var的声明提升到当前作用域的最前面,意思是是指无论 var 出现在一个作用域的哪个位置,这个声明都属于当前的整个作用域,在其中到处都可以访问到。只有变量声明才会提升,对变量赋值并不会提升。
//正常代码
console.log(a);//undefined
var a = 1;
//预解析
var a;
console.log(a);//undefined
a = 1;
补充:变量提升
JS执行过程先后分为编译和执行两步:
-
编译
在浏览器中运行的代码会先进行编译,在编译后,会生成两个东西:
执行上下文、可执行代码。
执行上下文就是 JS 代码的运行环境,里面会保存变量、函数、函数的this指向、函数的参数等信息。所有的声明语句都会在编译时被解析并保存在对应的上下文中。
可执行代码按字面理解就是“可以被执行的代码”。那什么代码可以被执行呢?目前我的理解是:除了声明语句之外的语句,比如赋值语句、函数调用语句等
-
执行
在这个过程,就是我们熟悉的 JS 引擎会一行一行地执行编辑阶段生成的可执行代码
(补充来自,作者:笑飞 链接:https://www.jianshu.com/p/704648f316ce 来源:简书)
var声明的变量在“编译阶段”的“执行上下文”时,被解析保存在所有代码的前面,当处于“执行阶段”时会先被执行。
三、let
1.let 声明的作用域
let 声明的变量具有块作用域的特征:
a. 内层变量不会覆盖外层变量
b.用来计数的循环变量不会泄露为全局变量
//在同一快状作用域,let声明的变量,不可以重复声明
function f(){
let a = 1;
let a = 2;//出错
}
//let 声明的变量不存在变量提升。即, let 声明存在暂时性死区(TDZ)。
let a = 1;
console.log(a);//1
console.log(b);//Uncaught ReferenceError: b is not defined
let b = 2;
2.var与let比较:for循环
//此时i是全局变量,循环输出结果为:10个10
for (var i = 0; i < 10; i++) {
//延时器属于异步函数,不会立即执行,
//经过1s后,循环已经结束,全局变量i已经变成10
setTimeout(function(){
console.log(i);
},100)
};
//此时i是属于块级作用域,循环输出结果为:0-9
for (let i = 0; i < 10; i++) {
// 每一轮都会形成一个私有的块级作用域,并且有一个私有的变量i,分别存储每一轮循环的索引
setTimeout(function(){
console.log(i);
},100)
};
四、const
const保证的并不是变量的值不能改动,而是变量指向的那个内存地址不能改动。对于基本类型的数据(数值、字符串、布尔值),其值就保存在变量指向的那个内存地址,因此等同于常量。但对于引用类型的数据(主要是对象和数组)来说,变量指向数据的内存地址,保存的只是一个指针,const只能保证这个指针是固定不变的,至于它指向的数据结构是不是可变的,就完全不能控制了。
(摘要来自:优快云博主「前端编程之家」的原创文章,遵循CC 4.0 BY-SA版权协议,
原文链接:https://blog.youkuaiyun.com/xiaoqingrong/article/details/119153274)
补充:为什么vue3中声明响应式变量经常用const:
因为 Vue 的响应式系统是通过属性访问进行追踪的,因此我们必须始终保持对该响应式对象的相同引用。如果用let/var会丢失链接。
文章参考:
优快云链接:https://blog.youkuaiyun.com/xiaoqingrong/article/details/119153274
简书链接:https://www.jianshu.com/p/704648f316ce
优快云链接:Js中var,let,const的区别_js const let var的区别_Cirrod的博客-优快云博客