🌐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) 吧!

相关推荐
ErMao4 小时前
深入理解let、const和var
前端
IT_陈寒4 小时前
SpringBoot 3.2新特性实战:这5个隐藏功能让开发效率翻倍🚀
前端·人工智能·后端
涛哥AI编程4 小时前
【AI编程干货】Token成为硬通货后,我的7000字Claude Code精算准则
前端·ai编程
IT_陈寒4 小时前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升70% 🚀
前端·人工智能·后端
南山安4 小时前
面试必考点: 深入理解CSS盒子模型
javascript·面试
golang学习记4 小时前
从0死磕全栈之深入理解 Next.js 中的 NextResponse:API 详解与实战示例
前端
木易士心4 小时前
CSS 中 `data-status` 的使用详解
前端
木易士心4 小时前
JavaScript 数组的核心操作方法,从基础到高级
前端
TimelessHaze4 小时前
🧱 一文搞懂盒模型box-sizing:从标准盒到怪异盒的本质区别
前端·css·面试
VOLUN4 小时前
Vue3 中 watch 第三个参数怎么用?6 大配置属性 + 场景指南
前端·javascript·vue.js