为什么说不会高阶函数的前端,连中级都算不上?

91 阅读3分钟

一、什么是高阶函数?

一句话:

高阶函数 = 把函数当数据用的函数
只要满足下面任意一条,它就是高阶:

  1. 接收一个或多个函数作为参数
  2. 返回一个函数

二、为什么你要关心?

维度传统写法高阶函数写法
复用复制粘贴抽象一次,处处调用
可读命令式嵌套声明式管道,像读句子
测试需要 mock 整块逻辑纯函数粒度小,测单点
扩展改老代码加新函数,无侵入

三、日常开发 5 大“现成”高阶函数

// 1. map:映射
[1, 2, 3].map(x => x * 2);          // [2, 4, 6]

// 2. filter:过滤
[55, 80, 95].filter(s => s >= 60);  // [80, 95]

// 3. reduce:归纳
[1, 2, 3, 4].reduce((a, b) => a + b, 0); // 10

// 4. find / some / every...
// 5. Promise.then / async 本质也是高阶

四、手写 map —— 3 分钟造轮子

function myMap(arr, fn) {
  const res = [];
  for (let i = 0; i < arr.length; i++) res.push(fn(arr[i], i));
  return res;
}

console.log(myMap([1, 2, 3], x => x ** 2)); // [1, 4, 9]

五、进阶实战 1:防抖(debounce)

场景:输入框连续打字,停止 500 ms 后才发请求。
核心:高阶函数返回新函数,内部维护定时器状态。

const debounce = (fn, delay = 500) => {
  let timer = null;
  return function (...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
};

// 使用
const search = debounce(q => fetch(`/search?q=${q}`), 500);
document.querySelector('input')
        .addEventListener('input', e => search(e.target.value));

六、进阶实战 2:节流(throttle)

场景:滚动监听,每 200 ms 最多执行一次。
思路:记录上一次执行时间。

const throttle = (fn, wait = 200) => {
  let last = 0;
  return function (...args) {
    const now = Date.now();
    if (now - last >= wait) {
      last = now;
      fn.apply(this, args);
    }
  };
};

window.addEventListener('scroll', throttle(() => {
  console.log('滚动触发', Date.now());
}, 200));

七、进阶实战 3:柯里化(curry)

把多参函数变成单参链式调用,轻松生成配置函数。

const curry = fn =>
  function curried(...args) {
    return args.length >= fn.length
      ? fn.apply(this, args)
      : (...next) => curried(...args, ...next);
  };

const add = (a, b, c) => a + b + c;
const curriedAdd = curry(add);

console.log(curriedAdd(1)(2)(3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6

八、组合函数 compose:从右到左的管道

const compose = (...fns) => x =>
  fns.reduceRight((v, f) => f(v), x);

// 实战:先取绝对值,再开方,再四舍五入
const pipeline = compose(Math.round, Math.sqrt, Math.abs);
console.log(pipeline(-16)); // 4

九、高阶组件(HOC):React 里的高阶函数

function withLoading(Component) {
  return function ({ isLoading, ...props }) {
    return isLoading ? <div>Loading...</div> : <Component {...props} />;
  };
}

const ButtonWithLoading = withLoading(Button);

十、调试技巧:如何快速识别高阶函数?

  1. 看签名:fn(()=>...)() => return function
  2. 看调用:const newFn = xxx(fn)newFn()
  3. 看命名:withXxxcreateXxxdebouncecurry 大概率高阶

十一、常见面试追问

  1. map vs forEach 区别?
    map 返回新数组,forEach 无返回、只副作用。
  2. 防抖节流差异?
    防抖合并多次为一次;节流按固定频率执行。
  3. 手写 Promise.all?
    本质是高阶函数:接收一组函数(或 thenable)返回新 Promise。

十二、总结 & 思维导图

高阶函数
├─ 参数是函数:map / filter / reduce / debounce / throttle
├─ 返回是函数:curry / compose / withLoading
└─ 核心价值:抽象行为、延迟执行、声明式组合

记住一句话:

当你开始把函数当乐高积木,而不是死代码,你就掌握了高阶函数。


如果文章对你有帮助,点个 ⭐️ 鼓励一下!