news 2026/7/29 20:45:22

JS/TS 编码规范实战:Vue 场景变量 / 函数 / 类型标注避坑|编码语法规范篇

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
JS/TS 编码规范实战:Vue 场景变量 / 函数 / 类型标注避坑|编码语法规范篇

【Vue/JS/TS】+【前端日常开发】:从【变量声明/函数写法/类型标注】到【落地实操】,彻底搞懂【前端可维护代码】的最佳写法,避开团队协作高频坑!

📑 文章目录

  • 一、先定一个总原则:让代码回答 3 个问题
  • 二、变量声明:const 优先,let 必要;别用 var
    • 2.1 规则一:默认用 const,能不变就不变
    • 2.2 规则二:对象/数组“内容可变”要自觉
    • 2.3 规则三:作用域要清楚,尽量避免“跨块复用同名”
    • 2.4 变量命名(你会在 Vue 里反复用到)
  • 三、函数写法:优先“清晰 + 可复用”;区分声明与箭头
    • 3.1 规则一:函数做工具就写“函数声明”,做回调就写“箭头函数”
    • 3.2 规则二:箭头函数逻辑简单就用隐式返回;复杂就用大括号 + 显式 return
    • 3.3 规则三:参数处理清晰,默认值优先,避免“神秘 undefined”
    • 3.4 规则四:尽量“早返回”,减少深层嵌套
    • 3.5 规则五:纯函数优先,副作用要“隔离”
  • 四、TS 类型标注:标注边界,能推断就推断;别滥用 any
    • 4.1 规则一:不要到处写类型;优先让 TS 推断简单情况
    • 4.2 规则二:公开函数/工具函数,建议给入参和返回值
    • 4.3 规则三:类型别写成“装饰品”,要覆盖真实约束
    • 4.4 规则四:联合类型要配合“判别方式”或类型保护(type guard)
    • 4.5 规则五:空值处理要“可读”,优先 ?? / 可选链 ?.
    • 4.6 规则六:尽量少用类型断言(as),它只能当“最后一层保险”
  • 五、一套完整实战示例:Vue 场景下的变量/函数/类型怎么选
    • 5.1 TS 版本:推荐写法(简洁又规范)
    • 5.2 反例:同样的需求,用 JS/TS 常见写法会怎么“变味”
  • 六、日常落地清单:写完代码前你可以自检这 6 条
  • 🔍 系列模块导航

同学们好,我是 Eugene(尤金),一名多年中后台前端开发工程师。

(Eugene 发音 /juːˈdʒiːn/,大家怎么顺口怎么叫就好)

很多前端开发者都会遇到一个瓶颈:

代码能跑,但不够规范;功能能实现,但维护起来特别痛苦;

一个人写没问题,一到团队协作就各种混乱、踩坑、返工。

想写出干净、优雅、可维护的专业代码,

靠的不是天赋,而是体系化的规范 + 真实实战经验

这一系列《前端规范实战》,我会用大白话 + 真实业务场景

不讲玄学、不堆理论,只分享能直接落地的规范、标准与避坑指南。

帮你从「会写代码」真正升级为「会写优质、可维护、团队级别的代码」。


做了 7 年前端后我越来越确定:规范不是“为了显得严谨”,而是为了在你每天写的代码里,减少歧义、降低出错率、让团队更快读懂。尤其是 Vue 项目里,代码往往会被拆到很多文件、很多watch/effect/computed里,变量声明、函数写法、类型标注只要稍微“不自洽”,后面就会反复踩同一类坑。

这篇文章不讲玄学底层原理,只讲“日常写代码到底怎么选、为什么这么选、踩坑会踩在哪”,并且每个规则都给出小白也能照着用的完整示例。你可以直接把它当成“编码时的选择题”。

一、先定一个总原则:让代码回答 3 个问题

写任何一段 JS/TS 代码,都尽量让读者(包括未来的你)在 3 秒内看懂:

  1. 这段代码的“东西”是什么(变量/参数/返回值的语义)
  2. 这段代码会不会变化(变量是否可变、函数是否有副作用)
  3. 类型上有哪些约束(TS 能推断就推断,推断不了就明确标注边界)

接下来我们按你关心的 3 个核心语法部分来落地:变量声明 / 函数写法 / 类型标注


二、变量声明:const优先,let必要;别用var

2.1 规则一:默认用const,能不变就不变

在 JS 里,变量声明最容易带来的 bug 是“以为不会变,结果被改了”,然后你在别处使用了旧值,出现错位、渲染异常、计算结果不对。

推荐:

  • “只赋值一次”的变量:用const
  • “需要重新赋值”的变量:用let
  • **不使用 **var(作用域、提升行为更容易造成误解)
反例(可读性差 + 未来容易被改)
lettotal=0;for(constpofproducts){total+=p.price;}total=total*1.1;// 未来改动时很容易忽略“total”本来不该变
正例(更清晰:total 的含义更稳定)
consttotal=products.reduce((sum,p)=>sum+p.price,0);constdiscountTotal=total*1.1;

⬆ 返回目录

2.2 规则二:对象/数组“内容可变”要自觉

很多人以为const obj = {}就代表“不能改”,这不成立。const只是保证变量绑定不被重新指向,但对象内部仍然可以被改。

你可以这样理解:

  • const:变量名别换指向(不要再obj = xxx
  • 对象内部修改:要么明确接受可变,要么尽量用不可变写法(更适合状态管理)
反例(隐蔽的可变)
constuser={name:'Alice',age:20};user.age=21;// 读者可能以为你在做不可变更新,但你在原地修改
正例(不可变更新:更利于追踪变更)
constuser={name:'Alice',age:20};constupdatedUser={...user,age:21};

⬆ 返回目录

2.3 规则三:作用域要清楚,尽量避免“跨块复用同名”

let/const都是块级作用域(block scope)。同一个块里避免反复声明、避免在不同层级用同名变量,会让读者在脑内“跳转”。

反例(同名遮蔽,踩坑常见)
letkeyword='Vue';if(search){letkeyword=search;// 遮蔽了外层 keyword,后续你可能以为 keyword 一直是同一个}
正例(用更明确的变量名)
letkeyword='Vue';if(search){keyword=search;}

⬆ 返回目录

2.4 变量命名(你会在 Vue 里反复用到)

下面是我建议的“能直接用”的命名习惯:

  1. 普通值:camelCase,语义清晰(例如userNametotalPrice
  2. 布尔值:优先加语义前缀is/has/can/should(例如isLoadinghasMore
  3. 数组:复数名itemsusersproducts
  4. 事件/回调:onXxx(例如onSubmitonClose
  5. 临时变量:尽量短但别乱缩写(例如tmp可以,但别变成tx1这种不可读)

⬆ 返回目录


三、函数写法:优先“清晰 + 可复用”;区分声明与箭头

3.1 规则一:函数做工具就写“函数声明”,做回调就写“箭头函数”

这不是绝对,但能让团队形成一致的阅读节奏:

  • 作为“可复用工具函数”(文件顶部、export、util):倾向function xxx(...) {}
  • 作为“回调”(例如map/filter/watch里的一次性逻辑):倾向const xxx = () => {}或内联箭头
例子:工具函数用声明
functionformatMoney(cents){return(cents/100).toFixed(2);}
例子:回调用箭头
consttotal=items.reduce((sum,item)=>sum+item.price,0);

⬆ 返回目录

3.2 规则二:箭头函数逻辑简单就用隐式返回;复杂就用大括号 + 显式 return

简单表达式:

constisHot=(p)=>p.score>=90;

复杂逻辑:

constnormalizeProduct=(p)=>{constprice=p.priceCents??0;return{...p,price};};

这样做的好处是:读者不用猜你的函数到底会不会做额外工作。

⬆ 返回目录

3.3 规则三:参数处理清晰,默认值优先,避免“神秘 undefined”

很多坑来自这种写法:你在函数里不断判断x && ...,结果逻辑变得很难读。

反例(读者要脑内推导大量情况)
functioncalc(min,max){if(min&&max)returnmax-min;if(min)returnmin;return0;}
正例(用默认值 + 明确语义)
functioncalc(min=0,max=0){if(max>0)returnmax-min;returnmin;}

⬆ 返回目录

3.4 规则四:尽量“早返回”,减少深层嵌套

Vue 写watch或处理筛选时,最常见的代码风格问题就是深层if/else

反例(嵌套过深)
functionfilterProducts(products,keyword){constres=[];for(constpofproducts){if(keyword){if(p.name.includes(keyword)){res.push(p);}}else{res.push(p);}}returnres;}
正例(早返回,逻辑更顺)
functionfilterProducts(products,keyword){if(!keyword)returnproducts;returnproducts.filter((p)=>p.name.includes(keyword));}

⬆ 返回目录

3.5 规则五:纯函数优先,副作用要“隔离”

在 Vue 里:

  • 计算数据(computed)尽量纯:同样输入得到同样输出

  • 请求/日志/写状态这类副作用放到合适的地方:actionswatch回调内部等

纯函数示例:

functioncalcCartTotal(items){returnitems.reduce((sum,it)=>sum+it.quantity*it.price,0);}

副作用示例:

asyncfunctionloadProducts(api){constres=awaitapi.getProducts();// 这里才开始处理“请求结果到状态”的逻辑returnres;}

⬆ 返回目录


四、TS 类型标注:标注边界,能推断就推断;别滥用any

TS 的核心目标不是“把代码变长”,而是让你在最该出错的地方更早发现问题。所以类型标注要遵循一个非常实用的策略:

规则总纲:在“边界处”标注类型,在“内部”尽量让 TS 推断。

边界通常是:

  • 函数参数 / 返回值(尤其是对外暴露的函数)
  • API 请求数据的入口
  • 对象结构很复杂、很容易写错的地方

4.1 规则一:不要到处写类型;优先让 TS 推断简单情况

反例(冗长但没带来额外安全)
constkeyword:string='Vue';constpage:number=1;
正例(短且不牺牲安全)
constkeyword='Vue';constpage=1;

⬆ 返回目录

4.2 规则二:公开函数/工具函数,建议给入参和返回值

尤其是你写到 util、通用函数、团队会复用的逻辑里。

typeMoneyCents=number;functionformatMoney(cents:MoneyCents):string{return(cents/100).toFixed(2);}

⬆ 返回目录

4.3 规则三:类型别写成“装饰品”,要覆盖真实约束

你要的是“约束”,不是“占位”。例如 API 数据通常是最危险的边界。

场景:商品列表接口

假设接口返回结构如下:

  • id必须存在且是字符串
  • priceCents可能是数字
  • tags可能为空

我们在 TS 里可以这样建模:

typeProduct={id:string;name:string;priceCents:number;tags?:string[];};typeFilters={keyword?:string;minPriceCents?:number;maxPriceCents?:number;};

如果你在后续筛选里把priceCents当成字符串用,TS 就能在你写代码时提醒你。

⬆ 返回目录

4.4 规则四:联合类型要配合“判别方式”或类型保护(type guard)

反例(看起来能编过,但可能埋雷)
functiongetLabel(v:string|number){// 你没有区分类型就直接当字符串用returnv.toUpperCase();// number 没有 toUpperCase}
正例(判别联合 + 分支清晰)
functiongetLabel(v:string|number){if(typeofv==='string')returnv.toUpperCase();returnString(v);}

⬆ 返回目录

4.5 规则五:空值处理要“可读”,优先??/ 可选链?.

很多 Vue/TS 项目坑来自null/undefined混用。建议你在严格模式下保持习惯:

  • 有默认值:优先用??
  • 可能为 null:优先用?.
  • 避免到处写强行断言as
constpriceCents=product.priceCents??0;constfirstTag=product.tags?.[0]??'';

⬆ 返回目录

4.6 规则六:尽量少用类型断言(as),它只能当“最后一层保险”

as可以让 TS 假装你说的是对的,但如果你其实判断错了,就会把运行时风险带回来。

更推荐写“类型保护”:

functionisProduct(value:any):valueisProduct{return(value&&typeofvalue.id==='string'&&typeofvalue.name==='string'&&typeofvalue.priceCents==='number');}

⬆ 返回目录


五、一套完整实战示例:Vue 场景下的变量/函数/类型怎么选

下面这个示例我会做成“你可以直接套进项目的写法”。场景:商品列表页需要:

  1. 获取商品(边界)

  2. 根据筛选条件计算展示列表(纯函数优先)

  3. 格式化金额(工具函数)

  4. 更新 UI 所需的数据(状态层处理副作用)

5.1 TS 版本:推荐写法(简洁又规范)

typeProduct={id:string;name:string;priceCents:number;tags?:string[];};typeFilters={keyword?:string;minPriceCents?:number;maxPriceCents?:number;};functionformatMoney(cents:number):string{return(cents/100).toFixed(2);}functionmatchesFilters(p:Product,filters:Filters):boolean{constkeyword=filters.keyword??'';constminPrice=filters.minPriceCents??0;constmaxPrice=filters.maxPriceCents??Number.POSITIVE_INFINITY;constbyKeyword=keyword?p.name.includes(keyword):true;constbyMin=p.priceCents>=minPrice;constbyMax=p.priceCents<=maxPrice;returnbyKeyword&&byMin&&byMax;}functionbuildDisplayList(products:Product[],filters:Filters){// 纯函数:同样输入得到同样输出returnproducts.filter((p)=>matchesFilters(p,filters)).map((p)=>({id:p.id,title:p.name,priceText:formatMoney(p.priceCents),tags:p.tags??[],}));}

你可以注意到这些“规范点”在一起工作时的效果:

  • 变量:默认用const,只有需要重新赋值才用let(此例基本不用let

  • 函数:工具函数用声明,回调用箭头;逻辑清晰

  • 类型:只在关键边界处建模(Product/Filters),内部让 TS 推断

⬆ 返回目录

5.2 反例:同样的需求,用 JS/TS 常见写法会怎么“变味”

// 反例:不建模,滥用 any,导致可读性和安全性都下降functionbuildDisplayList(products:any[],filters:any){constres=[];for(constpofproducts){// p.priceCents 可能不是 number,你没约束也没处理if(filters.keyword&&!p.name.includes(filters.keyword))continue;constpriceText=(p.priceCents/100).toFixed(2);// 运行时才知道会不会炸res.push({id:p.id,title:p.name,priceText,tags:p.tags});}returnres;}

这个反例会带来三个典型问题:

  • 可读性:any让读者无法判断结构是什么

  • 可维护性:未来接口一变,你不会在编译期得到提醒

  • 风险滞后:错误往往到运行时才暴露

⬆ 返回目录


六、日常落地清单:写完代码前你可以自检这 6 条

你不需要背很多条,只要养成“写完快速自检”的习惯:

  1. 这段代码里我有没有“随便用 let/var”,而其实只需要const

  2. 有无对象内部被我悄悄改了,导致外部状态不可追踪?

  3. 函数是否逻辑被我写得很深?有没有可以拆成纯函数/工具函数?

  4. 回调里我是否写成了“既做判断又做副作用”的大杂烩?

  5. TS 里我有没有把关键边界参数/返回值用any或缺失类型,导致约束失效?

  6. null/undefined我有没有用清晰的??/?.处理?有没有靠“运气”写断言?

⬆ 返回目录


总结:简洁不是随便,规范是让你更快更稳

  • const优先:减少“变量会变”的认知成本,让代码更稳定

  • 函数写法要遵循“清晰表达”:工具函数清晰可复用,回调函数紧凑好读

  • TS 类型标注要守边界:能推断就推断,推断不了就在关键位置补上约束

  • 大多数线上坑不是你不会写,而是你“写了但读不懂 / 约束没生效 / 风险滞后到运行时”

⬆ 返回目录

🔍 系列模块导航

📝 编码语法规范

这是前端规范实战系列中第二个模块,当编码语法规范模块更新完成之后会附上此模块的跳转链接,方便同学们阅读学习。

更新中,敬请期待~

👉 跟着系列慢慢学,把技术功底扎扎实实地打牢~

📚 系列总览

前端规范实战系列」正在持续更新中,后续会整理一篇《前端规范实战系列全系列目录导航》,包含每篇文章简介 + 直达链接,方便大家按顺序、体系化学习。

更新中,敬请期待~

⬆ 返回目录


技术成长,从来不是比谁写得快,而是比谁写得稳、规范、可维护

哪怕每次只吃透一条规范,长期下来,差距会非常明显。

后续我会持续更新前端规范、工程化、可维护代码相关实战干货,

帮你告别面条代码、维护噩梦,在开发与面试中更有底气。

觉得有用欢迎点赞 + 收藏 + 关注,不错过每一篇实战内容。

我是 Eugene,与你一起写规范、写优质代码,我们下篇干货见~

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/14 14:48:29

性能基准测试案例:系统容量规划的科学实践

一、容量规划失效的代价&#xff1a;一个警示案例 某电商平台在2025年双十一期间遭遇的崩溃事故&#xff0c;揭示了容量规划失误的毁灭性后果&#xff1a; 故障现象&#xff1a;峰值流量达预期1.8倍时&#xff0c;支付接口响应延迟从200ms飙升至15秒 根本原因&#xff1a; 缓…

作者头像 李华
网站建设 2026/7/14 14:48:31

如何在电脑上编辑三星手机联系人

直接在三星手机上管理联系人有时不太方便&#xff0c;尤其是在需要一次性更新多个姓名、电话号码或电子邮件地址时。在手机的小屏幕上编辑大量联系人既耗时又令人沮丧。幸运的是&#xff0c;您可以轻松地在电脑上编辑三星手机联系人。本文介绍三种实用方法&#xff0c;帮助您轻…

作者头像 李华
网站建设 2026/7/14 14:48:30

小说下载开源工具fanqienovel-downloader:构建你的离线阅读库

小说下载开源工具fanqienovel-downloader&#xff1a;构建你的离线阅读库 【免费下载链接】fanqienovel-downloader 下载番茄小说 项目地址: https://gitcode.com/gh_mirrors/fa/fanqienovel-downloader 在数字阅读日益普及的今天&#xff0c;网络波动、流量限制和平台访…

作者头像 李华
网站建设 2026/7/14 14:48:29

Qwen3-4B-Instruct-2507优化升级:如何调整参数获得更佳生成效果

Qwen3-4B-Instruct-2507优化升级&#xff1a;如何调整参数获得更佳生成效果 1. 模型核心能力概述 Qwen3-4B-Instruct-2507作为阿里开源的最新文本生成模型&#xff0c;在保持轻量级架构&#xff08;40亿参数&#xff09;的同时&#xff0c;通过多项技术升级显著提升了生成质量…

作者头像 李华
网站建设 2026/7/14 14:48:30

CLUE模型构建方法、模型验证及土地利用变化情景预测实践技术应用

土地利用/土地覆盖数据是生态、环境和气象等领域众多模型的重要输入参数之一。基于遥感影像解译&#xff0c;可获取历史或当前任何一个区域的土地利用/土地覆盖数据&#xff0c;用于评估区域的生态环境变化、评价重大生态工程建设成效等。借助CLUE模型&#xff0c;实现对未来土…

作者头像 李华
网站建设 2026/7/14 14:48:34

NVIDIA DGX Spark实战指南:从开箱到AI模型高效部署

1. 开箱初体验&#xff1a;当PetaFLOP算力装进小盒子 第一次拿到NVIDIA DGX Spark时&#xff0c;我差点以为快递发错了货——这个边长仅15厘米、重量1.2公斤的金属方块&#xff0c;怎么看都不像宣传中"全球最小AI超级计算机"该有的样子。但当我撕开牛皮纸包装&#x…

作者头像 李华