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

来聊聊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

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

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

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

相关推荐
悟能不能悟2 小时前
jsp怎么拿到url参数
java·前端·javascript
程序猿小蒜2 小时前
基于SpringBoot的企业资产管理系统开发与设计
java·前端·spring boot·后端·spring
Mapmost2 小时前
零代码+三维仿真!实现自然灾害的可视化模拟与精准预警
前端
程序猿_极客3 小时前
JavaScript 的 Web APIs 入门到实战全总结(day7):从数据处理到交互落地的全链路实战(附实战案例代码)
开发语言·前端·javascript·交互·web apis 入门到实战
suzumiyahr3 小时前
用awesome-digital-human-live2d创建属于自己的数字人
前端·人工智能·后端
萧曵 丶3 小时前
Python 字符串、列表、元组、字典、集合常用函数
开发语言·前端·python
申阳3 小时前
Day 10:08. 基于Nuxt开发博客项目-关于我页面开发
前端·后端·程序员
拉不动的猪3 小时前
Webpack 与 Rollup 中 Tree-shaking 的实现原理与效果
前端·webpack·rollup.js
林太白3 小时前
跟着TRAE SOLO学习两大搜索
前端·算法
yunyi3 小时前
使用go的elastic库来实现前后端模糊搜索功能
前端·后端