吖蛋
2023/01/06阅读:89主题:默认主题
JavaScript代码简洁之道
JavaScript代码简洁之道
1.通过条件判断给变量赋值布尔值的正确姿势
// bad
if (a === 'a') {
b = true
} else {
b = false
}
// good
b = a === 'a'
2.在if中判断数组长度不为零的正确姿势
// bad
if (arr.length !== 0) {
// ...
}
// good
if (arr.length) {
// ...
}
3.同理,在if中判断数组长度为零的正确姿势
// bad
if (arr.length === 0) {
// ...
}
// good
if (!arr.length) {
// ...
}
4.简单的if判断使用三元表达式
// bad
if (a === 'a') {
b = a
} else {
b = c
}
// good
b = a === 'a' ? a : c
5.使用includes简化if判断
// bad
if (a === 1 || a === 2 || a === 3 || a === 4) {
// ...
}
// good
let arr = [1, 2, 3, 4]
if (arr.includes(a)) {
// ...
}
6.使用some方法判断是否有满足条件的元素或every检测所有元素都满足指定条件
// bad
let arr = [1, 3, 5, 7]
function isHasNum (n) {
for (let i = 0; i < arr.length; i ++) {
if (arr[i] === n) {
return true
}
}
return false
}
// good
let arr = [1, 3, 5, 7]
let isHasNum = n => arr.some(num => num === n)
// best
let arr = [1, 3, 5, 7]
let isHasNum = (n, arr) => arr.some(num => num === n)
7.使用forEach方法遍历数组,不形成新数组
// bad
for (let i = 0; i < arr.length; i ++) {
// ...
arr[i].key = balabala
}
// good
arr.forEach(item => {
// ...
item.key = balabala
})
8.使用filter方法过滤原数组,形成新数组
// bad
let arr = [1, 3, 5, 7],
newArr = []
for (let i = 0; i < arr.length; i ++) {
if (arr[i] > 4) {
newArr.push(arr[i])
}
}
// good
let arr = [1, 3, 5, 7]
let newArr = arr.filter(n => n > 4) // [5, 7]
9.使用map对数组中所有元素批量处理,形成新数组
// bad
let arr = [1, 3, 5, 7]
let newArr = []
for (let i = 0; i < arr.length; i ++) {
newArr.push(arr[i] + 1)
}
// good
let arr = [1, 3, 5, 7]
let newArr = arr.map(n => n + 1) // [2, 4, 6, 8]
10.巧用对象(数组)方法,避免使用for...in(for循环),使用Object.values快速获取对象键名
let obj = {
a: 1,
b: 2,
}
// bad
let values = []
for (key in obj) {
values.push(obj[key])
}
// good
let values = Object.values(obj) // [1, 2]
11.使用Object.keys快速获取对象键名
let obj = {
a: 1,
b: 2,
}
// bad
let keys = []
for (value in obj) {
keys.push(value)
}
// good
let keys = Object.keys(obj) // ['a', 'b']
12.解构数组进行变量值的替换
// bad
let a = 1
let b = 2
let temp = a
a = b
b = temp
// good
let a = 1
let b = 2
[b, a] = [a, b]
13.解构对象赋值
// bad
function getFullName (user) {
const firstName = user.firstName
const lastName = user.lastName
return `${firstName} ${lastName}`
}
// good
function getFullName (user) {
const { firstName, lastName } = user
return `${firstName} ${lastName}`
}
// better
function getFullName ({ firstName, lastName }) {
return `${firstName} ${lastName}`
}
14.解构时重命名简化命名(针对后端返回字段命名过长)
// bad
setForm (data) {
this.one = data.aaa_bbb_ccc_ddd
this.two = data.eee_fff_ggg
}
// good
setForm ({aaa_bbb_ccc_ddd, eee_fff_ggg}) {
this.one = aaa_bbb_ccc_ddd
this.two = eee_fff_ggg
}
// best
setForm ({aaa_bbb_ccc_ddd: one, eee_fff_ggg: two}) {
this.one = one
this.two = two
}
15.解构时设置默认值
// 针对非接口,处理逻辑功能函数建议按需要设置默认值,入参需要
// bad 功能函数不需要接口,入参就能给与默认值
function setForm ({name, age}) {
if (!age) age = 16 // age = age || 16
this.name = name
this.age = age
}
// good
function setForm ({name, age = 16}) {
this.name = name
this.age = age
}
// 针对接口的赋值推荐可不设置解构默认值
const getData = async ({id}) => {
const {local, warehouseList} = await apiXXXXX({id});
// 当参数需要默认值再做一次处理
warehouseList = warehouseList || [];
}
16.||短路符设置默认值
let person = {
name: '张三',
age: 38,
}
// bad
let name
if (!person.name) {
person.name = '佚名'
}
name = person.name
// good
let name = person.name || '佚名'
17.&& 用 ? 替代, 防止报错
// bad
let childrenName = person.children && person.childre.name
// good
let childrenName = person.childre?.name
18.字符串拼接使用模板字面量 ${}
let person = {
name: 'LiMing',
age: 18,
}
// bad
function sayHi (obj) {
console.log('大家好,我叫' + person.name = ',我今年' + person.age + '了')
}
// good
function sayHi (person) {
console.log(`大家好,我叫${person.name},我今年${person.age}了`)
}
// best
function sayHi ({name, age}) {
console.log(`大家好,我叫${name},我今年${age}了`)
}
19.无说明的参数
// bad
if (value.length < 8) { // 为什么要小于8,8表示啥?长度,还是位移,还是高度?
...
}
// good
const MAX_INPUT_LENGTH = 8;
if (value.length < MAX_INPUT_LENGTH) { // 一目了然,不能超过最大输入长度
...
}
20.命名过于啰嗦
// bad
let nameString;
let theUsers;
// good
let name;
let users;
21.长代码不知道啥意思,无说明
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(
address.match(cityZipCodeRegex)[1], //长代码不知道这个代表什么
address.match(cityZipCodeRegex)[2], //长代码不知道这个代表什么
);
// good
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
const [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode);
22.函数传参,传参无说明
// bad
page.getSVG(api, true, false); // true和false啥意思,一目不了然
// good
page.getSVG({
imageApi: api,
includePageBackground: true, // 一目了然,知道这些true和false是啥意思
compress: false,
})
23.先使用函数式编程,尽量不使用for循环编程
// bad
for(i = 1; i <= 10; i++) {
a[i] = a[i] +1;
}
// good
let b = a.map(item => ++item)
24.函数中过多的采用if else .. if else.. 过多
// bad
if (a === 1) {
...
} else if (a ===2) {
...
} else if (a === 3) {
...
} else {
...
}
// good 看需要是否更换为策略模式
switch(a) {
case 1:
....
case 2:
....
case 3:
....
default:
....
}
// good
if (a === 1) { // 大概率的往上提
...
return;
}
if (a === 2) {
...
return;
}
if (a === 3) {
...
return;
}
...
25.在编程中少用else
// bad
if (subject === 'Mockingbird') {
return author === 'Harper Lee'
} else {
return author === 'Nue'
}
// good
if (subject === 'Mockingbird') {
return author === 'Harper Lee'
}
return author === 'Nue'
26.减少副作用,尽可能使用没有副作用的纯函数
// bad
function addItemToCart (cart, item, quantity = 1) {
const alreadyInCart = cart.get(item.id) || 0
cart.set(item.id, alreadyInCart + quantity)
return cart
}
// good
function addItemToCart (cart, item, quantity = 1) {
const cartCopy = new Map(cart)
const alreadyInCart = cartCopy.get(item.id) || 0
cartCopy.set(item.id, alreadyInCart + quantity)
return cartCopy
}
27.减少使用链式赋值
// bad
var a = b = c = 1
// good
var a = 1
var b = 1
var c = 1
28.变量声明
// bad
var a, b, c
// good
var a
var b
var c
29.使用字面量值创建对象或数组
// bad
const a = new Object{}
// good
const a = {}
// bad
const items = new Array()
// good
const items = []
30.请使用对象属性值的简写方式
// bad
const item = {
job: job
}
// good
const item = {
job
}
31.对象属性值的简写方式要和声明式的方式分组
const job = 'FrontEnd'
const department = 'JDC'
// bad
const item = {
sex: 'male',
job,
age: 25,
department
}
// good
const item = {
job,
department,
sex: 'male',
age: 25
}
32.使用拓展运算符 ... 复制数组,浅拷贝不满足时,使用lodash的深拷贝
const items = []
const itemsCopy = []
// bad
const len = items.length
let i
for (i = 0; i < len; i++) {
itemsCopy[i] = items[i]
}
// good
itemsCopy = [...items]
33.函数需要回传多个值时,请使用对象的解构,而不是数组的解构
// bad
function doSomething () {
return [top, right, bottom, left]
}
// 需要考虑数据的顺序
const [top, xx, xxx, left] = doSomething()
// good
function doSomething () {
return { top, right, bottom, left }
}
// 此时不需要考虑数据的顺序
const { top, left } = doSomething()
34.优先使用.来访问对象属性,不满足再使用[]
const joke = {
name: 'haha',
age: 28
}
// bad
const name = joke['name']
// good
const name = joke.name
35.先考虑Map(映射)是否满足,不满足再考虑使用数组
// 不推荐
const SellingTypeList = [
{ label: 'common Carton', value: 1 },
{ label: 'common Pcs', value: 2 },
{ label: 'common Pack', value: 3 },
];
// 推荐
const SellingType = {
CommonCarton: 1,
CommonPcs: 2,
CommonPack: 3,
}
// 当有需要时再写
const SellingTypeStr = {
[SellingType.CommonCarton]: 'common Carton',
[SellingType.CommonPcs]: 'common Pcs',
[SellingType.CommonPack]: 'common Pack',
}
// better
enum SellingType {
CommonCarton = 1,
CommonPcs = 2,
CommonPack = 3,
}
const SellingTypeStr = {
[SellingType.CommonCarton]: 'common Carton',
[SellingType.CommonPcs]: 'common Pcs',
[SellingType.CommonPack]: 'common Pack',
}
36.delete超过2个以上使用lodash的omit或者解构赋值
var object = {
'a': 1,
'b': '2',
'c': 3,
'd': 4,
...
};
// bad
delete object.a
delete object.c
delete object.d
// good
_.omit(object, ['a', 'c', 'd']);
// OR
const { a, c, d, ...newObject } = object;
作者介绍