var与let、const的区别
一、var声明的变量会挂载在window上,而let和const声明的变量不会
var a = 10;
console.log(a,window.a); //100 100
let b = 10;
console.log(b,window.b) // 10, undefined
const c = 10;
console.log(c,window.c) // 1 undefined
二、var声明变量会存在变量提升,let和const不存在变量提升——也称预解析
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声明的变量不会进行任何的提升,我们一定要先声明赋值再使用
三、let和const声明形成块作用域,而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
四、同一个作用域下let和const不能声明同名变量,而var可以
//var允许声明同名变量,后面的会将前面覆盖
var a = 10;
console.log(a); //10
var 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;
}