前几天面试了个工作了五年的前端,我问他const和let有什么区别,他说"就是写法不一样"。我再问他async/await的原理是什么,他想了半天说是"ES7的新特性"。

这种情况在职场上还挺常见的。很多人学JS就是冲着框架去的,基础概念反而一知半解。等项目做大了,遇到奇怪的问题就束手无策。我当年也犯过同样的错误,所以今天想聊聊现代JS开发里那些容易被忽略但很重要的东西。

变量声明别再稀里糊涂

说真的,到现在还有人在代码里用var。问起来就说"习惯了",或者"不知道有什么区别"。区别大了去了,var有变量提升,容易出bug,代码可读性也差。

const用来声明常量,let用来声明变量,就这么简单。如果一个值不会被重新赋值,用const肯定没错。好处是什么?代码读起来更清楚,别人一看就知道这个变量不会被改。

还有个容易被忽略的:解构赋值真的很好用。比如要从对象里取三四个属性,传统写法是一堆user.name、user.age之类的,现在直接const { name, age, email } = user,代码清爽多了。

异步编程要搞清楚原理

async/await用久了,有时候会忘记它到底是什么。很多人只知道"前面加async,后面加await,就能拿到结果"。但回调地狱是怎么来的、Promise又是怎么解决这个问题的,这些概念不清楚,就很难写出高质量的异步代码。

我建议大家有空去看看Promise的源码,不用全看懂,就看个基本原理。知道了then和catch是怎么串联起来的,对async/await的理解会更深。

还有一个常见的坑:忘记catch错误。async函数里的await如果报错了,你需要try-catch包裹着,否则这个错误就丢了。生产环境里很多奇怪的bug就是这么来的。

模块化不是把所有代码堆一起

刚学前端的时候,我习惯把所有JS写在一个文件里,代码长了就ctrl+f找。后来组件化开发多了,才慢慢理解模块化的好处。

一个模块只做一件事,出了错好排查。不同功能的代码分开,团队协作的时候也不会冲突。import和export的用法要熟练,命名导出和默认导出什么时候用,也有讲究。

动态导入也很有用。页面首次加载的时候不需要那些边角功能的代码,用户点到了再加载,用户体验会好很多。特别是后台管理系统这种很多人不会用到所有功能的场景,效果很明显。

类型检查这件事

TS现在火得一塌糊涂,但我见过太多人写着TS却用着any。类型定义写得像流水账,该有的约束一个没有,那跟写JS有什么区别?

我的建议是,如果项目决定用TS,就好好用。interface和type的区别要搞清楚,泛型至少会用。类型定义宁可写详细点,也不要全是any。开始会慢一点,但后期维护省心很多。

如果项目不用TS,那至少在JS里养成类型思维。函数参数要校验,返回值类型要考虑清楚。别什么都用undefined和null表示,语义化一点。

性能优化要从细节做起

之前做项目,有个页面加载特别慢,用了各种优化手段效果都不好。后来定位到问题,是一个循环里重复创建大对象。改成对象池复用,性能直接翻倍。

这类问题很难一眼看出来,需要借助工具。Chrome的Performance面板挺好用的,能看到每个函数的执行时间。哪里是瓶颈,一目了然。

还有一些基本的:避免深拷贝、用事件委托而不是给每个元素绑定事件、图片懒加载、减少重排重绘。这些都知道,但写代码的时候容易忘。养成习惯很重要。

错误处理不能敷衍

很多人在代码里直接写console.log(error),然后就不管了。这不叫错误处理,这叫掩耳盗铃。

错误要分类型处理:网络错误可以重试,参数错误要提示用户,业务错误要根据错误码做不同响应。什么都不管的话,出了问题只能靠日志慢慢查。

全局错误监听也要加。unhandledrejection和error事件,监听一下,能避免很多线上问题。别等用户来反馈了,你才知道出了错。

代码风格要统一

团队开发最怕的就是代码风格不统一。你用四个空格缩进,他用两个空格,他用tab。各种格式混在一起,代码审查的时候光看格式就看花眼。

eslint和prettier配合起来用,能解决大部分问题。提交前自动检查,不符合规范的代码直接拦下来。省得大家为了格式问题吵来吵去。

还有一些是工具检查不出来的,比如命名。你叫getUserById,他叫fetchUserInfo,另一个叫selectUser。都是做同一件事,名字却五花八门。这种最好在项目规范里写清楚命名规则。

最后

JS生态变化快,新东西层出不穷。但不管用什么框架、什么工具,基础概念永远是根本。把ES6+的特性吃透,把异步编程搞明白,把类型思维培养起来,比追着新框架跑重要得多。

建议大家每年都回头看看自己写过的代码,可能都会有"这写的什么玩意儿"的感觉。说明在进步。继续加油。