js中var,let,const的区别及相关面试题讲解

 更新时间:2025年05月21日 09:45:52   作者:遗憾随她而去.  
这篇文章主要介绍了js中var,let,const的区别及相关面试题的相关资料,var函数作用域且提升,let块作用域无提升,const需初始化且不可重新赋值,强调let在循环中避免闭包问题,const限制仅针对引用,需要的朋友可以参考下

一. var 

1. var声明作用域 

使用var在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁: 

function test(){
  var a='hi' //局部变量
}
test()
console.log(a)//报错

//如果省略操作符 
function test(){
  a='hi' //全局变量
}
test() 
console.log(a) //'hi' 
//去掉var操作符之后,就变成了全局变量,只要调用一次test(),就会定义这个变量,并且可以在函数外部访不  
//推荐这样做,容易造成混乱

 2. 声明提升 ,也就是把所有变量声明都拉倒函数作用域的订单,此外,使用var声明同一个变量也没有问题;

function test(){
  console.log(a)
  var a='hi'
}
test() // undefined 

//等价于下列代码 
function test(){
  var a; 
  console.log(a)
  a='hi'
}

//声明同一个变量
function foo(){
  var a=10;
  var a=20;
  var a=30;
  console.log(a); 
}
foo(); //30

二. let 

1.let 跟var 的作用差不多,最明显的区别是,let声明的范围是块作用域,而var声明的范围是函数作用域 

//var 没有块作用域   块作用域是是函数作用域的子集 因此let也没有函数作用域
if(true){
 var name='matt'; 
 let age=26;
 console.log(name); //matt
 console.log(age); //26
}
console.log(name); //matt 
console.log(age); //age没有定义 

2. let 也不允许同一个块作用域出现冗余声明

var name; 
var name; 

let age;
let age; // age已经声明过了


//不在同一个块中可以重复声明 
let age=30;
console.log(age); //30
if(true){
 let age=26;
 console.log(age); //26
}

//在同一作用域内,不能混用 var 和 let 声明同名变量,否则会抛出 SyntaxError。

var name;
let name;//SyntaxError 

let age; 
var age; //SyntaxError

3. let 有暂时性死区 就是let声明的变量不会在作用域中被提升

// var 会提升
console.log(name); //undefined 
var name='Matt'

//let 不会提升.
console.log(age)// age没有定义
let age=16; 
在let声明之前的执行瞬间被称为"暂时性死区"

4. 使用let在全局作用域中声明的变量不会变成window对象的属性(var声明的则会)

var name='matt'
console.log(window.name); //matt 

let age=26
console.log(window.age); //undefined 

5.for循环中的let声明和var 声明

在let 出现之前,for循环定义的迭代变量会渗透到循环体外部;

for(var i=0;i<5;++i){
  //循环逻辑
}
console.log(i); //5

//改成使用let之后,这个问题就消失了,因为迭代变量的作用域仅限于for循环内部;
for(let i=0;i<5;++i){
 //循环
}
console.log(i); //没有定义

 还有个面试经常提及的问题,在for循环的循环体内定义一个定时器,循环结束后,查看结果

 1. 使用var 的时候 

for(var i=0;i<5;i++){
  setTimeout(()=>console.log(i),1000)
}
//你可能会以为输出0,1,2,3,4
//实际会输出5,5,5,5,5

解释: 我们知道,循环结束的条件是i=5, 从事件循环机制的角度来分析上面的代码,是这样的: 

调用堆栈:用于存储程序按顺序调用的函数的详细信息的堆栈。

   1. 首先在Call Stack(调用堆栈)中执行同步代码var i=0,此时i小于5,执行下一行代码,发现是一个setTImeout计时器,它是一个宏任务,这个时候会被推入到WEB API中,计时器开始执行; 

   2. 执行i++,在Call Stack中进入下一次迭代循环,重复上面操作 

    其实上面的代码中WEB API一共存放过5个计时器,每个计时器进入到WEB API, 1s之后就会被推      入到QUEUE(队列)中(最后队列中也会有5个计时器),等待EVENT LOOP(事件循环)检测到Call           Stack为空时,将QUEUE中每一个计时器推入到Call Stack执行,最后全部代码执行完成,从调用栈       中退出

       使用var 的时候,由于每一次循环得到的迭代变量会被上一次的覆盖,最后i=5,退出循环,迭代变           量也被泄露了出去了,每一个计时器引用同一个i,因此会打印5个5

     《JavaScript高级程序设计4》: 是因为在退出循环时,迭代变量保存的是导致循环退出的值 : 5 

       在之后执行超时逻辑时,所有i都是同一个变量,因而输出的都是同一个最终值

2.使用let 的时候 

for(let j=0;j<5;j++){
  setTimeout(()=>{
    console.log('j',j) //1 2 3 4 5
  })
}

 个人理解 : for每次循环都是不同的块级作用域,let声明的变量是块级作用域的,所以也不存在重复声明的问题

《JavaScript高级程序设计4》: 在使用let声明迭代变量时,js引擎在后台会为每个迭代循环声明一个新的迭代变量,每个setTimeout引用的都是不同变量实例,所以console.log()输出的使我们期望的值,也就是循环执行过程中每个迭代变量的值 

这种每次迭代声明一个独立变量实例的行为适用于所有风格的for循环,包括for-in和for-of循环

三. const 

1. const 的行为与let基本相同,唯一一个虫重要的区别是用它声明变量时必须同时初始化变量,且尝试修改const声明的变量会导致运行时的错误

const age=26;
age=36; //TypeError: 给常量赋值 

2.const声明的限制只适用于它指向变量的引用,换句话说,如果const变量引用的是一个对象,那么修改这个对象内部的属性并不违反const的限制 

const person={ }
person.name='Matt'; //ok 

3. js引擎会为for循环中的let声明分别创建独立的变量实例,虽然const变量跟let变量很相似,但是不能用const 来声明迭代变量(因为迭代变量会自增);

for (const i=0; i<10;++i)() //TypeError: 给常量赋值

总结 

到此这篇关于js中var,let,const的区别及相关面试题讲解的文章就介绍到这了,更多相关js中var,let,const区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用JavaScript判断图片加载状态的几种方法

    使用JavaScript判断图片加载状态的几种方法

    在网页开发中,判断图片是否加载完成是一个常见的需求,无论是为了预加载资源、实现懒加载还是进行性能监控,本文将详细介绍几种使用JavaScript判断图片加载状态的方法,需要的朋友可以参考下
    2025-08-08
  • 微信小程序新手教程之页面打开数量限制

    微信小程序新手教程之页面打开数量限制

    这篇文章主要给大家介绍了关于微信小程序新手教程之页面打开数量限制的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-03-03
  • layui之table checkbox初始化时选中对应选项的方法

    layui之table checkbox初始化时选中对应选项的方法

    今天小编就为大家分享一篇layui之table checkbox初始化时选中对应选项的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-09-09
  • 原生Javascript封装的一个AJAX函数分享

    原生Javascript封装的一个AJAX函数分享

    这篇文章主要介绍了原生Javascript封装的一个AJAX函数分享,本文是实际项目中提取出来的,简单易用,需要的朋友可以参考下
    2014-10-10
  • JS基于对象的链表实现与使用方法示例

    JS基于对象的链表实现与使用方法示例

    这篇文章主要介绍了JS基于对象的链表实现与使用方法,结合实例形式分析了链表的原理及javascript定义与使用链表的相关操作技巧,需要的朋友可以参考下
    2019-01-01
  • JS实现的3D拖拽翻页效果代码

    JS实现的3D拖拽翻页效果代码

    这篇文章主要介绍了JS实现的3D拖拽翻页效果,通过鼠标事件结合时间函数动态操作页面元素实现拖拽翻页的效果,需要的朋友可以参考下
    2015-10-10
  • WEEX环境搭建与入门详解

    WEEX环境搭建与入门详解

    这篇文章主要介绍了WEEX环境搭建与入门详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-10-10
  • JS使用正则截取两个字符串之间的字符串实现方法详解

    JS使用正则截取两个字符串之间的字符串实现方法详解

    这篇文章主要介绍了JS使用正则截取两个字符串之间的字符串实现方法,结合实例形式简单分析了JS正则匹配与截取操作的实现技巧,并拓展分析了数量词的概念与功能,需要的朋友可以参考下
    2017-01-01
  • JavaScript中关于base64的一些事

    JavaScript中关于base64的一些事

    base64 其实是一种编码转换方式, 将 ASCII 字符转换成普通文本, 是网络上最常见的用于传输8Bit字节代码的编码方式之一。这篇文章重点给大家介绍JavaScript中关于base64的一些事,感兴趣的朋友跟随小编一起看看吧
    2019-05-05
  • JavaScript 高效运行代码分析

    JavaScript 高效运行代码分析

    传统上,网页中不会有大量的脚本,至少脚本很少会影响网页的性能。
    2010-03-03

最新评论