石河子市网站建设_网站建设公司_Oracle_seo优化
2026/1/16 15:27:29 网站建设 项目流程


别再用var了!前端新人搞懂let和const少踩80%的坑

  • 别再用var了!前端新人搞懂let和const少踩80%的坑
    • 先甩结论:var 就是前任,早分早超生
    • 作用域:var 的“老好人” VS let/const 的“边界感”
    • 变量提升:var 先上车后补票,let/const 直接拒载
    • 暂时性死区(TDZ):别提前偷看美女洗澡
    • 重复声明:var 的“海王”属性
    • const 不是“常量”?锁的是引用地址!
    • for 循环 + 闭包:var 留下的史诗级天坑
    • 实战口诀:一把梭 const,不行再 let,var 留给考古队
    • Cannot assign to const ?三步排查不抓瞎
    • 骚操作:解构 + const,代码又短又安全
    • 真实项目踩坑合集
    • 写在最后的土味鸡汤

别再用var了!前端新人搞懂let和const少踩80%的坑

友情提示:本文全程碎碎念,代码片段多到像不要钱,建议收藏+边嗑瓜子边看。——来自一个曾被var坑到凌晨四点的老前端


先甩结论:var 就是前任,早分早超生

我第一次把var换成let的那一刻,感觉像是把用了十年的塑料拖鞋扔了,换上带气垫的新鞋——脚感瞬间不一样。
别急着翻文档,先给你整一段“血泪史”:

// 1. 循环里埋雷,炸得你亲妈都不认识for(vari=0;i<5;i++){setTimeout(()=>console.log(i),1000);// 55555,全是5}// 我当时盯着控制台,怀疑人生:i 不是 0 1 2 3 4 吗?怎么全变 5 了?// 2. 变量提升,代码还没写就先“被声明”console.log(hero);// undefined,不报错,但逻辑鬼畜varhero='ironMan';// 等价于:// var hero;// console.log(hero);// hero = 'ironMan';// 这感觉就像女神先答应你约会,再告诉你她其实有男朋友

看完这两行,你要是还能淡定地说“var 挺好”,那我敬你是条汉子。


作用域:var 的“老好人” VS let/const 的“边界感”

先别整什么“词法作用域”这种高端词,咱用菜市场比喻:

  • var就像广场舞大妈,音乐一响,整个广场她都能溜达,谁也拦不住。
  • let/const像戴口罩的社恐青年,只在自家楼道晃悠,出楼道就自动消失。

代码说话:

functionoldLadyDance(){if(true){varvegetables='大白菜';}console.log(vegetables);// 大白菜 ✅ 大妈跳完整条街}oldLadyDance();functionyoungGuyWalk(){if(true){letvegetables='西兰花';}console.log(vegetables);// ReferenceError ❌ 小伙只在楼道里出现}youngGuyWalk();

看到报错别慌,这就是let给你立规矩:变量只在最近的一层{}里活,出来就暴毙。
if/for/while时,顺手把var换成let,bug 直接少一半,亲测有效。


变量提升:var 先上车后补票,let/const 直接拒载

变量提升(hoist)这词听着像吊车,其实就一句话:
js 在编译阶段把声明提前,但赋值不提前。

// 1. var 的“老赖”操作console.log(a);// undefinedvara=1;// 2. let 的“零容忍”console.log(b);// ReferenceError: Cannot access 'b' before initializationletb=2;// 3. const 同理console.log(c);// ReferenceErrorconstc=3;

想更直观?把内存当酒店:

  • var订房时先把钥匙挂门上,不住也挂,导致你推门一看“undefined 垃圾房”。
  • let/const必须人到前台才给钥匙,提前偷看直接保安(TDZ)给你叉出去。

暂时性死区(TDZ):别提前偷看美女洗澡

TDZ 全称 Temporal Dead Zone,翻译过来就是“时间死区”,听着像科幻片,其实就是:

在代码真正跑到声明那一行之前,你碰都别想碰变量,碰就炸。

functiontdzDemo(){console.log(typeofhero);// ReferenceErrorlethero='Batman';}tdzDemo();

很多人用typeof判断有没有全局变量,结果在块级作用域里翻车了:
TDZ 内 typeof 也不管用!
记住:只要你在let/const声明之前访问,统统死啦死啦地。


重复声明:var 的“海王”属性

varname='Tony';varname='Stark';// 完全 OK,后者覆盖前者console.log(name);// Starkletname2='Tony';letname2='Stark';// SyntaxError: Identifier 'name2' has already been declared

看到报错别骂编译器,它是你亲哥:
团队协作时,别人如果顺手声明了同名变量,let 直接掀桌子,避免把 bug 藏到线上。
eslint:prefer-const+no-var双剑合璧,谁写var直接 CI 红屏,比 code review 还快。


const 不是“常量”?锁的是引用地址!

刚学const时,我天真地以为写const age = 18就能永远 18,结果对象属性说改就改,当场裂开:

constperson={name:'Lucy',age:18};person.age=19;// 完全 OK!console.log(person);// { name: 'Lucy', age: 19 }// 但你想换人?门都没有person={};// TypeError: Assignment to constant variable.

原理一句话:const 保证的是“绑定的内存地址”不变,不保证地址里的内容不变。
数组同理:

constnums=[1,2,3];nums.push(4);// ✅ 可以改内部nums=[];// ❌ 不能改引用

真想深度冻结?上Object.freeze()

constfrozenHero=Object.freeze({name:'Thor',level:99});frozenHero.level=100;// 静默失败,严格模式会抛 TypeErrorconsole.log(frozenHero.level);// 还是 99

注意:freeze只是浅冻结,嵌套对象还得递归冻,俗称“东北大板”:

functiondeepFreeze(obj){Object.freeze(obj);Object.getOwnPropertyNames(obj).forEach(prop=>{if(obj[prop]!==null&&typeofobj[prop]==='object'){deepFreeze(obj[prop]);}});returnobj;}

for 循环 + 闭包:var 留下的史诗级天坑

老代码里要是看到下面这种,别犹豫,直接 refactor:

varbtnList=document.querySelectorAll('button');for(vari=0;i<btnList.length;i++){btnList[i].onclick=function(){console.log('当前是第'+i+'个按钮');// 全是最后一个 i};}

为啥?var只有函数作用域,没有块级作用域,回调执行时i早已飙到btnList.length
三种解法,任君 pick:

// 1. 立即执行函数(IIFE),老派但稳for(vari=0;i<btnList.length;i++){(function(index){btnList[index].onclick=()=>console.log('当前是第'+index+'个按钮');})(i);}// 2. let 块级作用域,最优雅for(leti=0;i<btnList.length;i++){btnList[i].onclick=()=>console.log('当前是第'+i+'个按钮');}// 3. forEach 直接消灭索引烦恼btnList.forEach((btn,index)=>{btn.onclick=()=>console.log('当前是第'+index+'个按钮');});

实战口诀:一把梭 const,不行再 let,var 留给考古队

总结成一句人话:

默认全写const,后面发现要重新赋值,就地改成let
如果lint报警告,说明你变量设计得有问题,先思考再改,而不是退回到var

.eslintrc 推荐组合拳:

{"rules":{"no-var":"error","prefer-const":["error",{"destructuring":"all"}]}}

配合 vscode 的eslint --fix保存自动格式化,写var直接飘红,强迫症患者极度舒适。


Cannot assign to const ?三步排查不抓瞎

  1. 看是不是手残重新赋值

    constapi='https://api.xxx.com';api='https://new.xxx.com';// ❌ 直接 TypeError
  2. 看是不是想改 const 对象属性但操作失误

    constconfig={baseURL:''};config.baseURL='https://new.xxx.com';// ✅ 这是 OK 的
  3. 看是不是在严格模式 + eval 里花式作死
    严格模式对var的提升也会更苛刻,但一般项目都上 babel + eslint,这条很少踩。


骚操作:解构 + const,代码又短又安全

// 1. 数组解构const[first,second]=[10,20];console.log(first,second);// 10 20// 2. 对象解构重命名const{data:userData,error}=awaitfetchUser();if(error)throwerror;console.log(userData);// 3. 函数默认参数 + 解构functioncreateButton({text='确定',type='primary'}={}){console.log(text,type);}createButton();// 确定 primarycreateButton({text:'取消'});// 取消 primary

解构虽好,可不要贪杯:
嵌套层级太深时,要么用lodash/fpget,要么上TypeScript给类型,解构到第五层还不用类型,后期维护就是大型考古现场。


真实项目踩坑合集

  1. webpack 插件里忘记用 let 导致循环变量泄漏
    插件钩子函数里写for (var i),结果多个 chunk 共用同一个i,编译到一半直接串台,输出文件名全乱。
    varlet后世界瞬间安静。

  2. 在 node 脚本里用const声明 logger,误重新赋值

    constlogger=createLogger();logger=createLogger({level:'debug'});// 脚本直接崩

    线上 cron 任务挂了一夜,早上老板问我为什么报表没跑。
    从此 cron 脚本也加 eslint 检查,别问,问就是血泪。

  3. 老项目 jQuery 插件,全局 var 污染
    维护 2014 年的项目,里面全是var $btnvar index,各种$btn冲突,点击一个按钮三个插件一起响应。
    IIFE+let重构后,bundle 体积还小了 10%,鬼知道当年那么多全局变量是怎么跑起来的。


写在最后的土味鸡汤

写变量就像谈恋爱:
var是海王,见一个爱一个,谁都能覆盖,头顶一片青青草原;
let是老实人,一次只能一个,分手(离开作用域)就彻底断;
const是死心眼,一旦认定终身不改,对象属性可以一起长大,但想换人?门都没有。

别把“小细节”不当回事,工程化就是靠这些看似琐碎的约束,帮你把 80% 的 bug 掐死在娘胎里。
等你哪天在凌晨两点安心睡觉,而不用盯着 Sentry 报错时,你会回来点赞这篇文章的。

好了,瓜子嗑完,代码抄完,把var全删掉吧,下一篇文章见。

欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!


专栏系列(点击解锁)学习路线(点击解锁)知识定位
《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等
《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结
《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识
《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。
通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心
《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页
《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化
《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅
《python相关博客》持续更新中~Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具
《sql数据库相关博客》持续更新中~SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能
《算法系列相关博客》持续更新中~算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维
《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识
《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方
《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面
《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等
《photoshop相关博客》持续更新中~基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结
日常开发&办公&生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具

吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询