🤔面试官问你:什么是高阶函数?举例说明用到过的...

来聊聊js中一个超级实用的概念------高阶函数。别被这个名字吓到,其实它比你想象的要简单得多,而且每天都在用,只是你可能没意识到而已。

一、什么是高阶函数?

简单来说,高阶函数就是"操作函数的函数"。它有两种表现形式:

  1. 把函数当参数传递:就像你可以把数字、字符串传给函数一样,你也可以把函数作为参数传递
  2. 把函数当返回值:函数执行后不返回常规值,而是返回另一个函数
javascript 复制代码
// 1. 函数作为参数
function sayHi(greetingFn) {
  greetingFn(); // 调用传入的函数
}

sayHi(function() {
  console.log("你好呀!");
});

// 2. 函数作为返回值
function createGreeter() {
  return function() {
    console.log("我来自内部函数!");
  };
}

const myGreeter = createGreeter();
myGreeter(); // 输出:我来自内部函数!

二、为什么需要高阶函数?

想象一下,如果没有高阶函数,我们写代码会多麻烦:

  1. 事件处理没法写了(addEventListener需要传函数)
  2. 定时器没法用了(setTimeout需要传函数)
  3. 数组操作变得复杂(map、filter都用不了)

高阶函数让JavaScript变得灵活强大,是函数式编程的基础。

三、日常开发中的高阶函数

1. 数组的超级帮手

数组方法里到处都是高阶函数,我们来看几个最常用的:

map - 数组变形专家

javascript 复制代码
const prices = [10, 20, 30];
const discounted = prices.map(price => price * 0.9); // 打9折
console.log(discounted); // [9, 18, 27]

filter - 数组过滤器

javascript 复制代码
const numbers = [1, 2, 3, 4, 5];
const evens = numbers.filter(num => num % 2 === 0); // 只留偶数
console.log(evens); // [2, 4]

reduce - 数组计算器

javascript 复制代码
const cart = [
  { name: "苹果", price: 10 },
  { name: "香蕉", price: 20 },
  { name: "橙子", price: 15 }
];

const total = cart.reduce((sum, item) => sum + item.price, 0);
console.log(total); // 45

2. 异步编程好伙伴

setTimeout - 定时执行

javascript 复制代码
setTimeout(() => {
  console.log("3秒后执行");
}, 3000);

Promise.then - 异步处理

javascript 复制代码
fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log("获取到数据:", data));

3. 事件处理必备

javascript 复制代码
document.getElementById('myBtn').addEventListener('click', () => {
  console.log("按钮被点击啦!");
});

四、手把手教你写高阶函数

理解了概念后,我们来动手写几个实用的高阶函数:

1. 函数节流(throttle)

防止按钮重复点击或滚动事件频繁触发:

javascript 复制代码
function throttle(fn, delay) {
  let lastTime = 0;
  return function() {
    const now = Date.now();
    if (now - lastTime >= delay) {
      fn.apply(this, arguments);
      lastTime = now;
    }
  };
}

// 使用示例
const throttledScroll = throttle(() => {
  console.log("处理滚动...");
}, 200);

window.addEventListener('scroll', throttledScroll);

2. 数据校验器

javascript 复制代码
function createValidator(rules) {
  return function(data) {
    for (const [key, checkFn] of Object.entries(rules)) {
      if (!checkFn(data[key])) {
        return false;
      }
    }
    return true;
  };
}

// 使用示例
const validateUser = createValidator({
  name: name => name.length >= 2,
  age: age => age >= 18
});

console.log(validateUser({ name: "张三", age: 20 })); // true
console.log(validateUser({ name: "李", age: 15 })); // false

3. 缓存函数

javascript 复制代码
function memoize(fn) {
  const cache = {};
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache[key] === undefined) {
      cache[key] = fn.apply(this, args);
    }
    return cache[key];
  };
}

// 使用示例
const expensiveCalc = memoize(function(n) {
  console.log("长时间计算...");
  return n * n;
});

console.log(expensiveCalc(5)); // 输出"长时间计算..."然后返回25
console.log(expensiveCalc(5)); // 直接返回25,不再计算

五、高阶函数的链式调用

高阶函数最爽的地方就是可以像乐高积木一样组合使用:

javascript 复制代码
const products = [
  { name: "手机", price: 5999, stock: 10 },
  { name: "笔记本", price: 8999, stock: 5 },
  { name: "平板", price: 2999, stock: 20 }
];

// 找出价格低于8000的商品,打8折,然后计算总价
const total = products
  .filter(product => product.price < 8000)  // 先过滤
  .map(product => product.price * 0.8)      // 再打折
  .reduce((sum, price) => sum + price, 0); // 最后求和

console.log(total); // 输出打折后的总价

六、常见问题解答

Q:高阶函数会不会影响性能? A:确实会有轻微性能开销,因为多了函数调用。但在大多数情况下,代码可读性和维护性的提升远大于这点性能损失。只有在极端性能敏感的场景才需要考虑优化。

Q:箭头函数和高阶函数有什么关系? A:箭头函数让高阶函数写起来更简洁。比如arr.map(x => x*2)arr.map(function(x){ return x*2 })简洁多了。

Q:什么时候该自己写高阶函数? A:当你发现有多处相似代码,只有部分逻辑不同时,就可以考虑用高阶函数来抽象重复部分。

七、总结

高阶函数不是什么高深的概念,它就是:

  1. 能接收函数的函数
  2. 能返回函数的函数

日常开发中,我们其实经常在用高阶函数,比如:

  • 数组的map、filter、reduce
  • 定时器setTimeout
  • 事件监听addEventListener
  • Promise的then/catch

掌握高阶函数后,你会发现:

代码更简洁了
重复代码变少了
逻辑更容易理解了
抽象能力更强了

记住,学习高阶函数最好的方式就是多用、多练。刚开始可能会觉得有点绕,但用多了就会觉得特别自然。

相关推荐
阿华的代码王国1 小时前
【Android】RecyclerView实现新闻列表布局(1)适配器使用相关问题
android·xml·java·前端·后端
汪子熙1 小时前
Angular 最新的 Signals 特性详解
前端·javascript
Spider_Man1 小时前
前端路由双雄传:Hash vs. History
前端·javascript·html
南方kenny1 小时前
CSS Grid 布局:从入门到精通,打造完美二维布局
前端·javascript·css
小泡芙丫1 小时前
从买房到代码:发布订阅模式的"房产中介"之旅
前端·javascript
企鹅吧1 小时前
前端导出 pdf 与 跑马灯效果 最佳实践
前端·javascript·vue.js
南方kenny1 小时前
移动端适配的利器:lib-flexible 原理与实战
前端·javascript·react.js
沫小北1 小时前
HarmonyOS 自定义日期选择器组件详解
前端
大土豆的bug记录2 小时前
鸿蒙拉起系统定位和app授权定位
前端·javascript·harmonyos
用户47949283569152 小时前
mcp是怎么和大模型进行交互的,有哪些交互方式
前端·人工智能