🌐ES6 这 8 个隐藏外挂,知道 3 个算我输!

标签:ES6、JavaScript、性能优化、代码简化


"代码写得少,Bug 自然少。"------鲁迅(并没有说)

今天不聊 React、不聊 Vue,回到语言层,挖一挖那些"官方早就给了,但我们总自己造轮子"的 ES6 冷门 API。

它们每一个都经过浏览器真·原生实现,无 polyfill 也能跑一句顶五句,看完直接复制粘贴就能让同事惊呼"还有这种操作?"。


1. 数组拍平:flat / flatMap

场景:后端把树形结构一股脑塞给你,前端只想拿叶子节点。

js 复制代码
// 商品按类目嵌套:[[手机,耳机],[笔记本,鼠标]]
const goods = [['iPhone','AirPods'],['MacBook','MagicMouse']];

// 旧写法
const all = goods.reduce((a, b) => a.concat(b), []); 

// 新写法
const all = goods.flat();          // 默认 1 层
const deep = goods.flat(Infinity); // 无限层

bonusflatMap = map + flat(1),一次循环搞定"一对多"映射。

js 复制代码
const users = [{name:'张三',tags:'前端,TS'},{name:'李四',tags:'后端,Go'}];
const pairs = users.flatMap(u => u.tags.split(',').map(t => ({name:u.name, tag:t})));
// [{name:'张三',tag:'前端'}, {name:'张三',tag:'TS'}, ...]

2. 对象 ↔ 数组"瞬移":entries ↔ fromEntries

场景 :只想给对象做"过滤 / 映射 / 排序",又懒得写 reduce

js 复制代码
const score = { 语文:95, 数学:82, 英语:76 };

// 保留 >80 的学科
const pass = Object.fromEntries(
  Object.entries(score).filter(([k,v]) => v > 80)
);
// { 语文:95, 数学:82 }

URL 解析也能一行完成:

js 复制代码
const params = Object.fromEntries(new URLSearchParams('name=张三&age=25'));
// { name:'张三', age:'25' }

3. 字符串补全:padStart / padEnd

场景:时间、订单、身份证,位数必须对齐。

js 复制代码
const now = new Date();
const time = `${now.getHours().toString().padStart(2,'0')}:${now.getMinutes().toString().padStart(2,'0')}`;
// "09:05" 而不是 "9:5"

固定编号

js 复制代码
const orderId = '457';
const fullId = orderId.padStart(8, '0'); // "00000457"

4. 数组去重 + 集合运算:Set

场景:接口返回了 1w 条数据,里面重复 ID 占 30%。

js 复制代码
const ids = [3,5,5,7,3,9];
const unique = [...new Set(ids)];        // [3,5,7,9]

// 交集 / 差集,同样一行
const a = new Set([1,2,3]);
const b = new Set([3,4,5]);
const intersect = [...a].filter(v => b.has(v)); // [3]
const diff      = [...a].filter(v => !b.has(v)); // [1,2]

5. 解构"嵌套 + 默认值"

场景:接口字段经常缺失,还要做降级。

js 复制代码
function ajax({
  url,
  method = 'GET',          // 默认值
  timeout = 5000,
  headers: { token = '' } = {}  // 嵌套默认值
} = {}) {
  console.log(url, method, token);
}

深层安全取值

js 复制代码
const { address: { city, detail = '暂无' } = {} } = user;
// 无论 user.address 是否存在都不会报错

6. 真正"私有"属性:Symbol

场景:写工具库,怕用户覆盖你的内部字段。

js 复制代码
const _secret = Symbol('secret');
class Cache {
  [_secret] = new Map();
  set(k,v){ this[_secret].set(k,v); }
  get(k){ return this[_secret].get(k); }
}
const c = new Cache();
c['secret'] = 123;        // 不影响内部
console.log(c[_secret]);  // 外部拿不到

还能改 toString 标签

js 复制代码
class Queue {
  [Symbol.toStringTag] = 'Queue';
}
`${new Queue}`; // "[object Queue]"

7. 对象操作"统一入口":Reflect

场景:写 Proxy 拦截,总担心"死循环"。

js 复制代码
const proxy = new Proxy(target, {
  get(t, k){
    console.log('read', k);
    return Reflect.get(t, k); // 调用原始行为,安全
  }
});

安全删除

js 复制代码
const ok = Reflect.deleteProperty(obj, 'a'); // 返回布尔,可判断

8. 异步"扫尾"神器:finally()

场景:请求结束必须关 loading,成功失败都得关。

js 复制代码
function load(){
  showLoading();
  return fetch('/api/data')
    .then(render)
    .catch(showError)
    .finally(hideLoading); // 只写一次
}

结语:如何无痛养成"新习惯"?

  1. 代码评审刻意问一句 :这里能用 flatMap / fromEntries 吗?
  2. 立 Flag:连续三周在业务里用满这 8 个 API,每用一次给自己打 ★。
  3. 团队分享:把本文甩到群里,谁最晚在 PR 里用到,请全组奶茶 🧋。

"轮子"官方已经造好,下次再手写 reduce 去重,就罚自己抄十遍 flat(Infinity) 吧!

相关推荐
Nan_Shu_6142 分钟前
学习: Threejs (2)
前端·javascript·学习
G_G#10 分钟前
纯前端js插件实现同一浏览器控制只允许打开一个标签,处理session变更问题
前端·javascript·浏览器标签页通信·只允许一个标签页
@大迁世界26 分钟前
TypeScript 的本质并非类型,而是信任
开发语言·前端·javascript·typescript·ecmascript
GIS之路35 分钟前
GDAL 实现矢量裁剪
前端·python·信息可视化
是一个Bug38 分钟前
后端开发者视角的前端开发面试题清单(50道)
前端
Amumu1213840 分钟前
React面向组件编程
开发语言·前端·javascript
学历真的很重要41 分钟前
LangChain V1.0 Context Engineering(上下文工程)详细指南
人工智能·后端·学习·语言模型·面试·职场和发展·langchain
持续升级打怪中1 小时前
Vue3 中虚拟滚动与分页加载的实现原理与实践
前端·性能优化
GIS之路1 小时前
GDAL 实现矢量合并
前端
hxjhnct1 小时前
React useContext的缺陷
前端·react.js·前端框架