var与let、const的区别

154 阅读4分钟

var与let、const的区别

一、var声明的变量会挂载在window上,而letconst声明的变量不会

var a = 10;
console.log(a,window.a);  //100 100let b = 10;
console.log(b,window.b)  // 10, undefinedconst c = 10;
console.log(c,window.c)  // 1 undefined

二、var声明变量会存在变量提升,letconst不存在变量提升——也称预解析

console.log(a); 
var a = 10;
​
//预解析过程:
var a;
console.log(a)  // undefined ===》 声明,没有赋值,值默认是undefined
a = 10;
console.log(b); //报错
let b = 10;
​
//let声明的变量没有预解析,所以console.log(b)会报错,且报错信息是:Cannot access 'b' before initialization ==》在初始化之前无法访问b——简单来说,输出的b,不能在let声明的变量b前面。
​
//从中可以得知:let声明的变量不会进行任何的提升,我们一定要先声明赋值再使用
console.log(c);  //报错
const c = 10;
​
//const声明的变量和let声明的变量一样都没有预解析,所以console.log(c)也会报错,且报错信息是:Cannot access 'c' before initialization ==》在初始化之前无法访问c——简单来说,输出的c,不能在const声明的变量c前面。
​
//从中可以得知:const声明的变量不会进行任何的提升,我们一定要先声明赋值再使用

三、letconst声明形成块作用域,而var声明不会形成块作用域

if (true) {
    // var 声明的变量
    var a = 10;
    // let 声明的变量
    let b = 20;
}
console.log(a);  //10
console.log(b); // 报错,且报错信息为:b is not defined ==》 找不到b这个变量//为什么let声明的变量会报错,而var声明的变量就不报错呢?//因为var声明的变量没有块级(结构块,循环结构,分支结构...)作用域的概念(不是指函数),它会挂载到全局window。而let声明的变量有块级作用域,作用域是当前变量所有的结构块{}——有效作用域:从定义这个变量开始到它所在}结束
if (true) {
    // var 声明的变量
    var a = 10;
    // const 声明的变量
    const c = 30;
}
console.log(a);  //10
console.log(c);  // 报错,且报错信息为:c is not defined ==》 找不到c这个变量//为什么const声明的变量报错,而var声明的变量就不报错呢?//因为var声明的变量没有块级(结构块,循环结构,分支结构...)作用域的概念(不是指函数),它会挂载到全局window。而const声明的变量跟let声明的变量一样都有块级作用域,作用域是当前变量所有的结构块{}——有效作用域:从定义这个变量开始到它所在}结束
//结合上方 第三的观点,做下这题
var num = 10;
function fn1() {
    console.log(num); 
    var num = 20
    console.log(num); 
}
fn1()
console.log(num); 
​
//解题思路:
//先进行js预解析
var num;
// function 函数名称  这种函数也会进行提升
function fn1() {
    var num;
    console.log(num); // undefined
    // 先找自身作用域
    num = 20;
    console.log(num); // 20
}
num = 10;
fn1();
// 函数外部不能使用函数内部所声明的变量
console.log(num); //  10

四、同一个作用域下letconst不能声明同名变量,而var可以

//var允许声明同名变量,后面的会将前面覆盖
var a = 10;
console.log(a); //10var a = 20;
console.log(a) //20
//let不能声明同名变量
let a = 20;
let a = 30;
console.log(a); // 报错:Identifier a has already been declared ==》标识a已经被声明
​
//let能先声明后赋值
let a;
a = 20;
console.log(a) //20
//const不能声明同名变量
const b = 20;
const b = 20;
console.log(b);// 报错:Identifier 'b' has already been declared ==》标识b已经被声明
​
//const不能先声明后赋值,必须在声明的同时进行赋值
const b;
b = 20;
console.log(b); //报错:Missing initializer in const declaration ==》const声明中缺少初始化式
​
//const声明后,值不能再修改
const b = 20;
b = 30;
console.log(b);//报错:Assignment to constant variable. ==》赋值给常变量。
​
//const如果声明的是复合类型数据,可以修改其属性
const obj = {a:10};
obj.name = 'zs';
obj.a = 100;
console.log(obj);  // {a:100,name:'zs'}

五、暂存死区

var a = 10;
​
if(true){
    a = 10;    
    //在当前块作用域中存在a使用let/const声明的情况下,给a赋值20时,只会在当前作用域找变量a,    
    // 而这时,还未到声明时候,所以控制台报错:不能在初始化之前访问'a'   
    let a = 1;
}