浅谈JS中var和let的区别

686 阅读2分钟

变量提升

首先var声明的是一个全局变量,存在变量提升,那么什么是变量提升呢?在我们js中,代码的执行分成两步(1.预编译 2.自上而下执行):

1.预编译阶段:此时js解析器会找到当前作用域中所有的var、function,将它们放到当前作用域顶上进行提前定义和声明(注意:如果有给变量赋值,赋值操作不会被提前!) ->变量提升机制

例如,以下代码:

  console.log(i);
  var i = 1;
  //输出:undefined

相当于以下代码:

  var i;
  console.log(i);
  i = 1;

如果将var改成let,将会弹出一个错误,例:

console.log(i);
let i = 1;
//报错:ReferenceError: Cannot access 'i' before initialization
//说明let不存在变量提升,需要先声明后使用

2.自上而下执行:此时代码开始一步一步开始执行,遇到函数则进入函数作用域内

作用域

var : 全局作用域、函数作用域,没有块级作用域({})的概念。

let : 块级作用域({}) ,也可以创建全局变量

//例1:
//全局作用域:
for(var i = 0; i<10; i++){
}
console.log(i);
//将i提升至作用域顶端声明 -> 进入for循环,将i赋值为0 ->执行至退出for循环 ->执行console.log
//输出:10

//例2:函数作用域
function fun(){
    a = 10;//相当于全局变量
    var b = 20;//只在函数内部有效,外部无法访问
}
fun();
console.log(a);//输出10
console.log(b);//报错:ReferenceError: b is not defined

//例3:块级作用域
{
var a = 10;
}
console.log(a);
//输出:10
//不报错,var在块级作用域中声明的变量在全局有效,
//所以说var是没有块级作用域这个概念的,这没有意义
//例4:let声明块级作用域
{
let a = 10;
}
console.log(a);
//报错:ReferenceError: a is not defined
//块级作用域,以外的地方无法访问它
//例5:let声明全局作用域
let a = 10;
{
    console.log(a);//输出10
}
function s(){
    console.log(a);//输出10
}
s();
console.log(a);//输出10
//let在这里声明的是一个全局变量

重复声明

var: 可以多次声明

let: 不允许重复声明,在相同作用域内不能重复声明

//例1:var重复声明
var a = 10;
function s(){
    console.log(a);//输出undefined
    var a = 11;
    console.log(a);//输出11
}
s();
console.log(a);//输出10
var a;
console.log(a);//输出10
var a = 12;
console.log(a);//输出12

//例2:let重复声明
let a = 1;
{
    let a = 1;
    console.log(a);//输出1,a声明的作用域不同
}
//例3:
let a = 1;
{
    var a = 1;
    console.log(a);//报错:SyntaxError: Identifier 'a' has already been declared
}
//例4:
{
    let a = 1;
    let a = 2;
    console.log(a);//报错:SyntaxError: Identifier 'a' has already been declared
}

总结

区别:

  1. let不存在变量提升
  2. 块级作用域问题
  3. 暂时性死区(let)
  4. 不可重复声明

js初学者,文章有误还望各位大佬多多指正