var/let/const:变量与作用域实战选型|JS 基础语法与数据操作篇
【JS变量声明关键字】【前端日常开发】从【作用域与变量提升逻辑】到【实战选型落地】彻底搞懂var/let/const的最佳写法避开循环异步、重复声明、const赋值等高频坑 文章目录一、先搞清楚三个关键字分别是什么1.1 一句话区别1.2 作用域函数作用域 vs 块级作用域1.3 变量提升Hoisting与暂时性死区TDZ1.4 const 不是“完全不能改”二、日常写代码到底怎么选2.1 推荐原则可直接当规范用2.2 按场景选2.3 简单示例三、常见坑会踩在哪3.1 坑一循环里用 var回调里拿到的是“最后的那个值”3.2 坑二同一作用域里重复声明 let/const 会报错3.3 坑三const 声明时必须赋初值3.4 坑四以为 const 对象/数组“完全不能改”3.5 坑五老项目里 var 和 let/const 混用四、和“作用域”相关的两个小点4.1 块级作用域对 if/else 很有用4.2 模块、全局与 window五、总结一张表 一句话 本系列专栏导航同学们好我是 Eugene尤金一个拥有多年中后台开发经验的前端工程师~Eugene 发音很简单/juːˈdʒiːn/大家怎么顺口怎么叫就好你是否也有过明明学过很多技术一到关键时候却讲不出来、甚至写不出来你是否也曾怀疑自己是不是太笨了明明感觉会却总差一口气就算想沉下心从头梳理可工作那么忙回家还要陪伴家人。一天只有24小时时间永远不够用常常感到力不从心。技术行业本就是逆水行舟不进则退。如果你也有同样的困扰别慌。从现在开始跟着我一起心态归零利用碎片时间来一次彻彻底底的基础扫盲。这一次我们一起慢慢来扎扎实实变强。不搞花里胡哨的理论堆砌只分享看得懂、用得上的前端干货咱们一起稳步积累真正摆脱“面向搜索引擎写代码”的尴尬。一、先搞清楚三个关键字分别是什么1.1 一句话区别关键字出现时间作用域能否重复声明能否先使用再声明varES5函数作用域可以可以会提升letES6块级作用域不可以不可以暂时性死区constES6块级作用域不可以不可以暂时性死区用人话说var老写法按“函数”划分地盘容易踩坑。let按“块”划分地盘不能重复声明更符合直觉。const和let一样是块级但声明后不能重新赋值注意引用类型里的属性可以改。⬆ 返回目录1.2 作用域函数作用域 vs 块级作用域函数作用域var只认function不认if/for/while等块。functionfn(){if(true){vara1;}console.log(a);// 1 —— if 块挡不住 var}块级作用域let/const认{}包括if、for、while、单独{}。functionfn(){if(true){leta1;constb2;}console.log(a);// ReferenceError: a is not definedconsole.log(b);// ReferenceError: b is not defined}日常结论在块里声明的变量如果希望“只在这个块里有效”用let/const用var会“漏”到整个函数容易产生隐蔽 bug。⬆ 返回目录1.3 变量提升Hoisting/ˈhɔɪstɪŋ/ 与暂时性死区TDZps· TDZ全称Temporal Dead Zone 音标/ˈtempərəl/ /ded/ /zəʊn/var会提升先使用再声明也不会报错只是值为undefinedconsole.log(x);// undefinedvarx10;console.log(x);// 10let/const有暂时性死区在声明之前访问会报错console.log(y);// ReferenceError: Cannot access y before initializationlety10;日常结论养成“先声明、再使用”的习惯用let/const可以避免“还没赋值就被用”的坑。⬆ 返回目录1.4const不是“完全不能改”const限制的是绑定不能重新赋值不限制引用类型内部的修改。constobj{name:小明};obj.name小红;// ✅ 可以改的是对象内部obj{};// ❌ 报错不能换一个对象constarr[1,2,3];arr.push(4);// ✅ 可以arr[];// ❌ 报错所以const适合“这个变量指向的引用不变”的场景不是“对象/数组内容不能动”。⬆ 返回目录二、日常写代码到底怎么选2.1 推荐原则可直接当规范用默认用const只要这个变量不会在逻辑里被重新赋值就用const。包括对象、数组、函数、配置、导入的模块等。需要“会变”的变量用let例如循环计数器、会随逻辑重新赋值的中间变量、交换两数等。新代码里不用var除非维护老项目且项目约定用var否则一律let/const。⬆ 返回目录2.2 按场景选场景推荐原因导入模块、配置对象、API 地址等const不打算换引用普通对象、数组内容会增删改const引用不变只改内部for 循环里的下标 / 循环变量let每次迭代会变需要先声明、后面再赋值的变量letconst 声明时必须赋初值交换变量、累加器、临时中间变量let会重新赋值老项目、历史代码按项目规范能改则逐步改为 let/const避免混用加重混乱⬆ 返回目录2.3 简单示例// ✅ 用 const引用不变constAPI_BASEhttps://api.example.com;constuser{name:张三,age:25};user.age26;// 可以// ✅ 用 let会重新赋值letcount0;count;lettemp;if(condition)tempa;elsetempb;// ❌ 不要用 var新代码varoldStyle1;// 容易漏出块、提升导致误用⬆ 返回目录三、常见坑会踩在哪3.1 坑一循环里用 var回调里拿到的是“最后的那个值”for(vari0;i3;i){setTimeout(()console.log(i),100);}// 输出3, 3, 3共用一个 i循环结束后 i 已是 3正确写法用let每次迭代都是新的绑定。for(leti0;i3;i){setTimeout(()console.log(i),100);}// 输出0, 1, 2⬆ 返回目录3.2 坑二同一作用域里重复声明 let/const 会报错leta1;leta2;// SyntaxError: Identifier a has already been declaredvar可以重复声明不报错但可读性和维护性差。用let/const可以尽早发现“名字写重了”的问题。⬆ 返回目录3.3 坑三const声明时必须赋初值constx;// SyntaxError: Missing initializer in const declarationconsty1;// ✅如果“现在不知道值后面才赋值”用let。⬆ 返回目录3.4 坑四以为const对象/数组“完全不能改”再次强调const限制的是「变量与引用类型的绑定关系」变量不能指向新的引用地址而非对象的属性值 / 数组的元素值。我们可以修改的是 “引用类型内部的内容”比如对象的value、数组的元素。⬆ 返回目录3.5 坑五老项目里var和let/const混用同一函数里既有var又有let作用域和提升行为不一致排查问题会很难。建议新加的逻辑一律let/const老代码有机会就逐步替换成let/const。⬆ 返回目录四、和“作用域”相关的两个小点4.1 块级作用域对if/else很有用if(condition){constmessageyes;// 只用在这里}else{constmessageno;// 只用在这里}// message 在块外不可见不污染外部用var的话message会跑到整个函数里容易重名或误用。⬆ 返回目录4.2 模块、全局与 window在ES Module里顶层的const/let不会挂到window上和“全局变量”是两回事。在传统脚本里顶层var会变成window的属性。日常用模块 const/let减少全局污染。⬆ 返回目录五、总结一张表 一句话要点说明默认能用const就用const会重新赋值用let新项目/新代码不用var循环 异步/回调用let避免var的“最后一个值”const不能重新赋值但对象/数组内部可以改一句话日常写 JS默认const要改再用let别再写var。先把“选谁”的习惯固定下来再结合作用域和 TDZ 理解“为什么”就能少踩坑、代码也更清晰。⬆ 返回目录 本系列专栏导航 JS 基础语法与数据操作一、《var/let/const变量与作用域实战选型JS 基础语法与数据操作篇》二、《this、箭头函数与普通函数前端实战避坑指南 | JS 基础语法与数据操作篇》三、《对象解构赋值接口数据解包 10 个实战写法JS 基础语法与数据操作篇》四、《map/filter/reduce数组10个常用实战操作JS 基础语法与数据操作篇》五、《find/some/every/includes数组查找与判断实战用法JS 基础语法与数据操作篇》六、《sort/localeCompare对象数组排序与分组实战JS 基础语法与数据操作篇》七、《模板字符串 /split/join/ 正则字符串处理实战JS 基础语法与数据操作篇》八、《Date/dayjs日期时间处理实战JS 基础语法与数据操作篇》九、《try/catch/Promise前端错误处理实战JS 基础语法与数据操作篇》十、《import/export前端模块化实战JS 基础语法与数据操作篇》 跟着系列慢慢学把技术功底扎扎实实地打牢 更多内容TS/Vue/工程化等共47篇已整理成「全体系总目录」收藏后可一站式学习 系列总览想系统学习Vue3中后台开发收藏这份「全体系指南」47篇干货从基础到工程化全覆盖《前端基础实战JS/TS与Vue体系化扫盲47 篇完整目录 避坑》 每篇都配套实战场景避坑指南帮你摆脱「面向搜索引擎写代码」的尴尬⬆ 返回目录学习本就是一场持久战不需要急着一口吃成胖子。哪怕今天你只记住了一点点这都是实打实的进步。后续我还会继续用这种大白话、讲实战方式带大家扫盲更多前端基础。关注我不迷路咱们把那些曾经模糊的知识点一个个彻底搞清楚。如果你觉得这篇内容对你有帮助不妨点赞收藏下次写代码卡壳时拿出来翻一翻比搜引擎更靠谱。我是 Eugene你的电子学友我们下一篇干货见