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

相关推荐
爱上妖精的尾巴1 天前
5-20 WPS JS宏 every与some数组的[与或]迭代(数组的逻辑判断)
开发语言·前端·javascript·wps·js宏·jsa
excel1 天前
Vue3 响应式核心源码全解析:Dep、Link 与 track/trigger 完整执行机制详解
前端
前端大卫1 天前
一个关于时区的线上问题
前端·javascript·vue.js
whltaoin1 天前
中秋赏月互动页面:用前端技术演绎传统节日之美
前端·javascript·html·css3·中秋主题前端
UrbanJazzerati1 天前
考研英语深挖 “I wonder if it isn't...” —— 否定式疑问背后的肯定式锋利观点
面试
IT派同学1 天前
TableWiz诞生记:一个被表格合并逼疯的程序员如何自救
前端·vue.js
双向331 天前
CodeBuddy Code + 腾讯混元打造"AI识菜通"
面试
西洼工作室1 天前
CSS高效开发三大方向
前端·css
昔人'1 天前
css`font-variant-numeric: tabular-nums` 用来控制数字的样式。
前端·css