本文为翻译作品,原文链接:As a Front-end Engineer, 10 Useful JavaScript Coding Techniques That You Should Use
前言
过去,我写了很多垃圾代码,现在看起来简直糟糕透顶。
当我再次看到那些代码片段时,我甚至怀疑我是否适合做程序员。
因此,这里有 10 条 JavaScript 技巧,帮助你避免写出我曾经写过的那种垃圾代码。
1. Promise 回调地狱
Promises 提供了一种优雅的方式来处理 JavaScript 中的异步操作。这也是避免“回调地狱”的解决方案之一。从前我不理解它的意义,所以我这样实现我的功能:
- 首先获取用户的基本信息。
- 通过用户信息获取所有文章的简要总结。
- 通过文章简介获取文章详情。
// ❌
getUserInfo()
.then((userInfo) => {
getArticles(userInfo)
.then((articles) => {
Promise.all(articles.map((article) => getArticleDetail(article)))
.then((articleDetails) => {
console.log(articleDetails)
})
})
})
我根本没有充分利用 Promise。我们应该像下面的代码片段那样处理:
// ✅
getUserInfo()
.then(getArticles)
.then((articles) => {
return Promise.all(articles.map((article) => getArticleDetail(article)))
})
.then((articleDetails) => {
console.log(articleDetails)
})
2. 不处理错误消息
我经常只编写成功请求的代码逻辑,但忽略了请求失败的情况。
// ❌
const getUserInfo = async () => {
try {
const userInfo = await fetch('/api/getUserInfo')
} catch (err) {
}
}
这是不成熟的,我们应该给出用户友好的提示,而不是什么也不做。
// ✅
const getUserInfo = async () => {
try {
const userInfo = await fetch('/api/getUserInfo')
} catch (err) {
Toast(err.message)
}
}
3. 函数参数过多
当一个函数有太多参数时,它的可读性变差,甚至让我们困惑如何正确传递参数。
示例
我们想获取用户的一些基本信息,比如姓名、性别、年龄等。
// ❌
const getUserInfo = (name, age, weight, gender, mobile, nationality, hobby, address) => {
// ...
}
getUserInfo('fatfish', 100, 2000, ...)
这太糟糕了。如果你的同事这样写代码,你会打他吗?
实际上,当函数参数过多时,你应该使用对象来传递所需信息,这样其可读性和可扩展性将得到提高。
// ✅
const getUserInfo = (options) => {
const { name, gender, age, mobile, weight, nationality, hobby, address } = options
// ...
}
getUserInfo({
name: 'fatfish',
age: 100,
weight: 2000
// ...
})
4. 魔法数字
我的朋友们,你们有没有写过这样的代码?在许多地方使用数字进行逻辑判断看似正常。是的,它让我困惑于1
、2
、3
到底代表什么。
// ❌
// component1.js
if (status === 1 || status === 2) {
// ...
} else if (status === 3) {
// ...
}
// component2.js
if (status === 1 || status === 2) {
// ...
}
我们最好将这些数字定义为常量。
// ✅
// constants.js
export const STATUS = {
// 成年并且已实名认证
adultRealName: 1,
// 未成年并且已实名认证
minorRealName: 2,
// 未实名认证
notRealName: 3,
// ...
}
// component1.js
import { STATUS } from './constants.js'
if ([ STATUS.adultRealName, STATUS.minorRealName ].includes(status)) {
// ...
} else if (status === STATUS.notRealName) {
// ...
}
// component2.js
import { STATUS } from './constants.js'
if ([ STATUS.adultRealName, STATUS.minorRealName ].includes(status)) {
// ...
}
5. 使用 .length 判断字符串长度
大多数时候,我们使用 .length 并且可以安全地判断字符串的长度,但在表单输入的情况下你应该小心。
当我们输入 🍫 时,nameLen 的值是 2 — 这不奇怪吗?
// ❌
<input type="text" id="name">
<script>
const $name = document.getElementById('name')
$name.addEventListener('blur', () => {
const name = $name.value
const nameLen = name.length
// 输入: fatfish => nameLen: 7
// 输入: 🍫 => nameLen: 2
console.log(`name: ${name}, nameLen: ${nameLen}`)
}, false)
</script>
是的,有一个原因,猜猜是什么?
// ✅
<input type="text" id="name">
<script>
const $name = document.getElementById('name')
$name.addEventListener('blur', () => {
const name = $name.value
const nameLen = name.length
const spRegexp = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g
const nameRealLen = name.replace(spRegexp, '_').length
// 输入: fatfish => nameLen: 7, nameRealLen: 7
// 输入: 🍫 => nameLen: 2, nameRealLen: 1
console.log(`name: ${name}, nameLen: ${nameLen}, nameRealLen: ${nameRealLen}`)
}, false)
</script>
6. 从不写代码注释
我们经常抱怨别人,“为什么你不写代码注释?”但实际上,我自己从来不写!
// ❌
const fn = (dpr) => {
if (dpr >= 2) {
// ...
} else {
}
}
我的天,你知道‘dpr’是什么意思吗?我从未想过它表示窗口的 devicePixelRatio。
// ✅
// dpr:请为 window.devicePixelRatio 输入一个值
const fn = (dpr) => {
if (dpr >= 2) {
// ...
} else {
}
}
7. 无意义的代码注释
与不写代码注释相比,写无意义的代码注释更糟,因为这浪费了你的时间。
你不妨解释一下“a”是什么意思,或者使用有意义的变量名!
// ❌
let a = 1 // 将 "a" 的值设置为 1
8. 随机命名
过去,我常写一些变量命名随意的尴尬代码片段。
// ❌
const mw = 375
你应该给变量一个恰当且有意义的名字。
// ✅
const maxWidth = 375
9. 不删除已弃用的代码
很多时候,我们的网站会不断调整功能,有新的和已弃用的功能,但我总是担心将来会用到它们,所以我只是对它们进行注释,而不是删除它们。
实际上,这种担心完全没有必要,因为将来很可能不会用到它们。即使将来会用到,也可以通过‘git’追溯。
10. 单个组件代码超过一千行
我在一个组件中写过超过一千行的代码。这实在是太糟糕了,我们应该进一步将组件的功能拆分为更小的组件。
最后
感谢阅读。我期待着你的关注,并阅读更多高质量的文章。