var const 和 let 的区别
- 在es6中 变量的声明方式一共有6种分别是: var const let function class import ;
- 在这里我们主要来探讨一下 let const 和 var 的区别;
var 关键字声明变量
1. var 关键字 —> 声明变量的作用域
var 定义的变量,作用域没有块的概念,只要不是在函数内部,都属于全局作用域,可以跨块访问,不能跨函数访问
function foo(){ var a = 1; // 局部变量 } foo(); console.log(a); // 报错
在函数foo调用时 会创建变量a赋值1,在函数调用后变量销毁,所以在函数foo外调用变量a会报错.但是在函数内部如果省略关键词var的话,就不会报错,为什么呢?
function foo(){ a = 1; } foo(); console.log(a) // 1
此时,就引出了我们接下来要讨论的问题,变量提升. 在省略掉关键字var 之后,调用函数就会,自动定义一个全局变量a,并且在函数外部可以访问.为什么呢?
2 var 变量提升
js代码在执行之前会预编译的,这个过程包括变量提升,函数声明提升等等.而var关键字声明的变量在预编译阶段会被变量提升的所以以下代码不会摆错:
function foo(){ console.log(age); var age = 26 } foo(); undefined
在js代码预编译阶段 会将当前作用域下声明的变量,提升到当前作用于的最顶端.
let 关键字声明变量
2.1 let关键字 ----> 声明变量的作用域
- let关键字声明的变量,会产生一个块级作用域,变量引用必须在块级作用域内,在其他地方引用会爆出错误.
if(true){ let a = 1; console.log(a); // 1 } console.log(a); // 报错 // 此处if语句的代码块就会形成一个块级作用域
- let 不允许同一个块级作用域中声明的变量被重复声明
let a = 1; let a = 3; //报错 标识符a已经被声明
使用var 声明的变量和let声明的变量,循环里使用setTimeout定时器后循环结果如下代码:
if(var i= 0; i < 5; i++){ setTimeout(()=>console.log(i),0); } // 输出 5,5,5,5,5 if(let i = 0; i < 5; i++){ setTimeout(()=>console.log(i),0) } // 输出 0,1,2,3,4
let是在代码块中有效,var是在全局变量中有效.let只能声明一次,var可以多次声明
当同步代码执行完毕后,开始执行异步的setTimeout代码,执行setTimeout时需要从当前作用域内寻找一个变量 i,for循环执行完毕,当前 i=5,执行setTimeout时输出为5,任务队列中的剩余4个setTimeout也依次执行,输出为5。
下面的变量使用let声明的,当前的i只在当前作用域生效,每次循环的i其实都是一个新的变量,座椅setTimeout定是器里面的i其实是不同的变量,所以输出的是0-4.
const关键字声明变量
const声明变量的行为,跟let基本相同,唯一一个重要的区别是:
const声明变量的时候必须赋值,不赋值报错.const声明的基本数据类型的变量是不可以改变的,不可以被重新赋值的 是唯一的.
const a = 1;
a = 22; // 报错
const b = 123;
const b = 456; // 报错 不能重复声明
// 在块级作用域外不能使用变量
if(true){
const name = '赵四'
console.log(name) // 赵四
}
console.log(name)
暂时性死区
let const与var 变量不同的一个重要的区别,let const声明的变量不会在作用域中被提升.es6新增的let const关键字声明变量会产生块级作用域,如果变量在当前作用域中被创建出来,由于此时还未完成语法绑定,所以是不能被访问的,如果访问就会抛出错误.因此,在写运行流程进入作用域创建变量,到变量可以被访问之间的这段时间就被称为暂时性死区.