20个提高代码质量的js方法(比较新的)

1 阅读4分钟

里头是一些真实项目里确实好用、但很多人用得不熟的,而且是mdn比较新的了

1. Object.fromEntries()

把键值对数组转回对象。

const entries = [
  ['name', '张三'],
  ['age', 18]
];

const obj = Object.fromEntries(entries);

console.log(obj);
// { name: '张三', age: 18 }

Object.entries() 是反向操作。

特别适合“过滤对象字段”:

const params = {
  name: '张三',
  age: '',
  city: '苏州'
};

const result = Object.fromEntries(
  Object.entries(params).filter(([_, value]) => value !== '')
);

console.log(result);
// { name: '张三', city: '苏州' }

2. flatMap()

等于 map() + flat(1)

const list = [
  { name: 'A', tags: ['x', 'y'] },
  { name: 'B', tags: ['z'] }
];

const tags = list.flatMap(item => item.tags);

console.log(tags);
// ['x', 'y', 'z']

比这样更简洁:

list.map(item => item.tags).flat();

3. structuredClone()

真正好用的深拷贝。

const obj = {
  user: {
    name: '张三'
  }
};

const copy = structuredClone(obj);

copy.user.name = '李四';

console.log(obj.user.name);
// 张三

比这个靠谱很多:

JSON.parse(JSON.stringify(obj));

因为 JSON 那种写法会丢:

Date
Map
Set
undefined

等类型。


4. Promise.allSettled()

多个请求并行执行,即使其中一个失败,也能拿到全部结果。

const result = await Promise.allSettled([
  fetch('/api/a'),
  fetch('/api/b'),
  fetch('/api/c')
]);

console.log(result);

结果类似:

[
  {
    status: 'fulfilled',
    value: ...
  },
  {
    status: 'rejected',
    reason: ...
  }
]

特别适合:

首页多个接口
多个图层数据加载
多个统计模块
批量上传

如果你用 Promise.all(),其中一个失败,整体就直接 reject 了。


5. Promise.any()

谁先成功就用谁。

const result = await Promise.any([
  requestServerA(),
  requestServerB(),
  requestServerC()
]);

只要有一个成功:

result

就返回。

Promise.race() 不一样,race() 是“谁先结束”,失败也算。


6. AbortController

取消请求。

const controller = new AbortController();

fetch('/api/list', {
  signal: controller.signal
});

// 取消
controller.abort();

在 React 搜索框里非常有用。

例如用户连续输入:

苏
苏州
苏州市

前面的请求其实已经没意义了,可以取消掉。


7. URLSearchParams

处理 URL 参数不要自己拼字符串。

const params = new URLSearchParams({
  keyword: '燃气',
  page: '1',
  size: '20'
});

console.log(params.toString());

得到:

keyword=%E7%87%83%E6%B0%94&page=1&size=20

然后:

fetch(`/api/list?${params}`);

读取也很好用:

const params = new URLSearchParams(location.search);

console.log(params.get('page'));

8. Set

去重神器。

const list = [1, 2, 2, 3, 3, 3];

const result = [...new Set(list)];

console.log(result);
// [1, 2, 3]

字符串也一样:

const ids = ['a', 'b', 'a'];

const uniqueIds = [...new Set(ids)];

9. Map

比普通对象更适合做“映射表”。

const map = new Map();

map.set('001', {
  name: '张三'
});

map.set('002', {
  name: '李四'
});

console.log(map.get('001'));

非常适合:

id -> 数据
图层 id -> 图层实例
设备 id -> 设备详情

比如地图项目里:

const markerMap = new Map();

markerMap.set(item.id, marker);

以后:

const marker = markerMap.get(id);

比数组里每次 find() 高效很多。


10. Array.from()

把类数组对象转成真正数组。

const nodes = document.querySelectorAll('.item');

const list = Array.from(nodes);

然后就可以:

list.map(...)
list.filter(...)

还支持第二个参数:

const result = Array.from(
  document.querySelectorAll('.item'),
  item => item.textContent
);

一步拿文本。


11. Array.at()

取数组倒数元素特别舒服。

以前:

const last = list[list.length - 1];

现在:

const last = list.at(-1);

倒数第二个:

list.at(-2);

字符串也支持:

'hello'.at(-1);
// o

12. Object.groupBy()

非常适合按状态、类型分组。

例如:

const list = [
  { name: 'A', status: 'done' },
  { name: 'B', status: 'todo' },
  { name: 'C', status: 'done' }
];

const result = Object.groupBy(
  list,
  item => item.status
);

结果:

{
  done: [
    { name: 'A', status: 'done' },
    { name: 'C', status: 'done' }
  ],
  todo: [
    { name: 'B', status: 'todo' }
  ]
}

以前通常要自己写 reduce()

注意:这是比较新的 JS API,如果项目目标浏览器较老,要检查兼容性。


13. Object.hasOwn()

判断对象自身是否有某个属性。

推荐:

Object.hasOwn(obj, 'name');

而不是:

obj.hasOwnProperty('name');

例如:

const obj = {
  name: undefined
};

Object.hasOwn(obj, 'name');
// true

而:

obj.name !== undefined

是:

false

两者语义不同。


14. ??=

只有值是 null / undefined 才赋值。

config.timeout ??= 5000;

等价于:

if (config.timeout == null) {
  config.timeout = 5000;
}

||= 不同:

let count = 0;

count ||= 10;
// 10

但:

let count = 0;

count ??= 10;
// 0

业务代码里 ??= 通常更安全。


15. &&= / ||=

逻辑赋值运算符。

例如:

user.name ||= '匿名用户';

如果 user.name 是:

''
null
undefined
0
false

都会赋默认值。

而:

enabled &&= checkPermission();

等价于:

if (enabled) {
  enabled = checkPermission();
}

16. 可选调用 ?.()

很多人知道:

user?.name

但不知道函数也可以:

onSuccess?.();

比:

if (onSuccess) {
  onSuccess();
}

简洁很多。

React 组件里特别高频:

props.onChange?.(value);

17. 可选链访问数组 ?.[]

例如:

const first = data?.list?.[0];

如果:

data
data.list

不存在,都不会报错。

动态字段也支持:

const key = 'name';

const value = user?.[key];

18. Intl.NumberFormat

不要手写金额千分位。

const formatter = new Intl.NumberFormat('zh-CN');

formatter.format(123456789);

得到:

123,456,789

货币:

const formatter = new Intl.NumberFormat('zh-CN', {
  style: 'currency',
  currency: 'CNY'
});

formatter.format(1234.5);

得到类似:

¥1,234.50

19. Intl.DateTimeFormat

日期格式化也不一定非要装库。

const formatter = new Intl.DateTimeFormat('zh-CN', {
  year: 'numeric',
  month: '2-digit',
  day: '2-digit',
  hour: '2-digit',
  minute: '2-digit'
});

formatter.format(new Date());

用于普通展示其实已经很够用了。


20. crypto.randomUUID()

生成唯一 ID。

const id = crypto.randomUUID();

console.log(id);

类似:

550e8400-e29b-41d4-a716-446655440000

前端临时 ID 很好用:

const row = {
  id: crypto.randomUUID(),
  name: '新建记录'
};

比:

Date.now()
Math.random()

更规范。