百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

前端面试-js高阶函数的介绍和使用

itomcoil 2025-04-05 19:24 24 浏览

一、什么是高阶函数?

高阶函数满足以下任一条件:

  1. 接受函数作为参数
  2. 返回一个新的函数

高阶函数的核心思想是将函数视为“一等公民”,像操作数据一样操作函数。

二、高阶函数的常见用途

1. 数组方法(接受函数作为参数)

JavaScript 数组的许多内置方法都是高阶函数,典型例子包括:

  • map():对数组每个元素执行操作,返回新数组。
const numbers = [1, 2, 3];
const doubled = numbers.map(x => x * 2); // [2, 4, 6]

filter():筛选符合条件的元素。

const evens = numbers.filter(x => x % 2 === 0); // [2]

reduce():将数组元素累积为单个值。

const sum = numbers.reduce((acc, x) => acc + x, 0); // 6

find()some():查找元素或判断条件。

const firstEven = numbers.find(x => x % 2 === 0); // 2
const hasEven = numbers.some(x => x % 2 === 0); // true

高阶用法

一、函数组合与管道(Function Composition & Piping)

1.组合多个函数

将多个函数串联为一个新函数,实现数据处理流水线:

const compose = (...fns) => (initialValue) =>
  fns.reduceRight((acc, fn) => fn(acc), initialValue);

// 示例:字符串处理
const toUpperCase = str => str.toUpperCase();
const addExclamation = str => str + "!";
const reverse = str => str.split('').reverse().join('');

const processString = compose(reverse, addExclamation, toUpperCase);
console.log(processString("hello")); // "OLLEH! -> !OLLEH"

2.管道(从左到右执行)

与 compose 类似,但执行顺序相反:

const pipe = (...fns) => (initialValue) =>
  fns.reduce((acc, fn) => fn(acc), initialValue);

const processStringPipe = pipe(toUpperCase, addExclamation, reverse);
console.log(processStringPipe("hello")); // "HELLO! -> !OLLEH"

二、高阶函数的抽象模式

1.中间件模式(Middleware Pattern)

用于 Express、Redux 等框架的中间件系统:

const createMiddleware = (...middlewares) => {
  return (initialHandler) => {
    return middlewares.reduceRight(
      (next, middleware) => middleware(next),
      initialHandler
    );
  };
};

// 中间件示例
const logger = (next) => (action) => {
  console.log("Action:", action);
  return next(action);
};
const validator = (next) => (action) => {
  if (!action.type) throw new Error("Invalid action");
  return next(action);
};

// 组合中间件
const finalHandler = (action) => console.log("Handling:", action);
const applyMiddleware = createMiddleware(logger, validator);
const enhancedHandler = applyMiddleware(finalHandler);

enhancedHandler({ type: "TEST" }); // 输出日志并验证

2.依赖注入(Dependency Injection)

通过高阶函数实现解耦:

const createService = (dependencies) => (config) => {
  return {
    log: () => dependencies.logger.log(config.message)
  };
};

// 使用
const serviceFactory = createService({ logger: console });
const service = serviceFactory({ message: "Hello" });
service.log(); // 输出 "Hello"

三、高阶函数与异步编程

1.Promise 链的抽象

用高阶函数封装重复的异步逻辑:

const withRetry = (fn, retries = 3) => async (...args) => {
  for (let i = 0; i < retries i try return await fn...args catch error if i='== retries' - 1 throw error const fetchdata='()'> fetch("https://api.example.com/data");
const fetchWithRetry = withRetry(fetchData, 2);
fetchWithRetry().then(/* ... */);

2.异步函数组合

处理异步函数的流水线:

const asyncPipe = (...fns) => async (initial) => {
  return fns.reduce(async (accPromise, fn) => {
    const acc = await accPromise;
    return fn(acc);
  }, initial);
};

// 示例
const fetchUser = async (id) => ({ id, name: "John" });
const fetchPosts = async (user) => [{ userId: user.id, post: "Hello" }];
const processData = asyncPipe(fetchUser, fetchPosts);

processData(1).then(console.log); // 输出用户关联的帖子

四、惰性求值与高阶函数

通过高阶函数实现延迟计算:

const lazyMap = (fn) => function* (iterable) {
  for (const item of iterable) {
    yield fn(item);
  }
};

const lazyFilter = (predicate) => function* (iterable) {
  for (const item of iterable) {
    if (predicate(item)) yield item;
  }
};

// 使用生成器实现惰性计算
const numbers = [1, 2, 3, 4, 5];
const mapped = lazyMap(x => x * 2)(numbers);
const filtered = lazyFilter(x => x > 5)(mapped);

console.log([...filtered]); // [6, 8, 10]

五、状态管理与高阶函数

1.状态转换器

封装状态变更逻辑:

const withState = (initialState) => (reducer) => {
  let state = initialState;
  return (...args) => {
    state = reducer(state, ...args);
    return state;
  };
};

// 示例:计数器
const counterReducer = (state, action) => {
  switch (action) {
    case "INC": return state + 1;
    case "DEC": return state - 1;
    default: return state;
  }
};

const counter = withState(0)(counterReducer);
console.log(counter("INC")); // 1
console.log(counter("INC")); // 2

2.Redux 风格的 Store

模仿 Redux 的核心逻辑:

const createStore = (reducer, initialState) => {
  let state = initialState;
  const listeners = [];
  return {
    getState: () => state,
    dispatch: (action) => {
      state = reducer(state, action);
      listeners.forEach(listener => listener());
    },
    subscribe: (listener) => {
      listeners.push(listener);
      return () => listeners.splice(listeners.indexOf(listener), 1);
    }
  };
};

六、高级柯里化与部分应用

1.动态柯里化

支持任意数量参数的柯里化:

const curry = (fn) => {
  const curried = (...args) =>
    args.length >= fn.length
      ? fn(...args)
      : (...moreArgs) => curried(...args, ...moreArgs);
  return curried;
};

// 使用
const add = curry((a, b, c) => a + b + c);
console.log(add(1)(2)(3)); // 6
console.log(add(1, 2)(3)); // 6

2.占位符参数

实现灵活的部分应用(类似 Lodash 的 _):

const _ = Symbol("placeholder");
const partial = (fn, ...args) => (...newArgs) => {
  const finalArgs = args.map(arg => arg === _ ? newArgs.shift() : arg);
  return fn(...finalArgs, ...newArgs);
};

// 示例
const greet = (greeting, name) => `${greeting}, ${name}!`;
const sayHello = partial(greet, "Hello", _);
console.log(sayHello("Alice")); // "Hello, Alice!"

七、函数式编程库的底层实现

1.Functor(函子)

封装值并提供 map 方法:

class Functor {
  constructor(value) {
    this.value = value;
  }
  map(fn) {
    return new Functor(fn(this.value));
  }
}

// 使用
new Functor(2)
  .map(x => x * 3)
  .map(x => x + 1)
  .value; // 7

2.Monad(单子)

处理副作用或嵌套结构(如 Promise):

class Maybe {
  constructor(value) {
    this.value = value;
  }
  static of(value) {
    return new Maybe(value);
  }
  map(fn) {
    return this.value == null ? this : Maybe.of(fn(this.value));
  }
  flatMap(fn) {
    return this.value == null ? this : fn(this.value);
  }
}

// 使用
Maybe.of(null)
  .map(x => x.toUpperCase()) // 不会执行
  .flatMap(x => Maybe.of(x + "!")); // 安全跳过

八、性能优化技巧

1.记忆化(Memoization)

缓存函数结果:

const memoize = (fn) => {
  const cache = new Map();
  return (...args) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
};

// 使用
const factorial = memoize(n => n <= 1 ? 1 : n * factorial(n - 1));
console.log(factorial(5)); // 120 (仅计算一次)

2.惰性链式调用

避免不必要的中间数组(类似 Lodash 的链式调用):

const lazyChain = (data) => ({
  map: (fn) => lazyChain({
    *[Symbol.iterator]() {
      for (const item of data) yield fn(item);
    }
  }),
  filter: (fn) => lazyChain({
    *[Symbol.iterator]() {
      for (const item of data) if (fn(item)) yield item;
    }
  }),
  value: () => [...data]
});

// 使用
const result = lazyChain([1, 2, 3])
  .map(x => x * 2)
  .filter(x => x > 3)
  .value(); // [4, 6]

九、总结:高阶函数的深度价值

  1. 抽象复杂性:将多步骤逻辑封装为可复用的单元。
  2. 声明式编程:用 what to do 代替 how to do。
  3. 函数式模式:实现 Functor、Monad、IO 等高级模式。
  4. 性能优化:通过惰性计算和记忆化提升效率。
  5. 框架设计:支撑中间件、状态管理等架构模式。

实际应用建议

  • 在数据处理、异步流程、工具库开发中优先使用高阶函数
  • 结合 TypeScript 强化类型推导
  • 避免过度抽象,保持代码可读性
  • 使用 Lodash/fp、Ramda 等函数式库加速开发

通过深度应用高阶函数,可以将 JavaScript 代码提升到接近函数式语言(如 Haskell)的表达能力,同时保持 JavaScript 的灵活性。

相关推荐

Python编程实现求解高次方程_python求次幂
Python编程实现求解高次方程_python求次幂

#头条创作挑战赛#编程求解一元多次方程,一般情况下对于高次方程我们只求出近似解,较少的情况可以得到精确解。这里给出两种经典的方法,一种是牛顿迭代法,它是求解方程根的有效方法,通过若干次迭代(重复执行部分代码,每次使变量的当前值被计算出的新值...

2025-10-23 03:58 itomcoil

python常用得内置函数解析——sorted()函数

接下来我们详细解析Python中非常重要的内置函数sorted()1.函数定义sorted()函数用于对任何可迭代对象进行排序,并返回一个新的排序后的列表。语法:sorted(iterabl...

Python入门学习教程:第 6 章 列表

6.1什么是列表?在Python中,列表(List)是一种用于存储多个元素的有序集合,它是最常用的数据结构之一。列表中的元素可以是不同的数据类型,如整数、字符串、浮点数,甚至可以是另一个列表。列...

Python之函数进阶-函数加强(上)_python怎么用函数

一.递归函数递归是一种编程技术,其中函数调用自身以解决问题。递归函数需要有一个或多个终止条件,以防止无限递归。递归可以用于解决许多问题,例如排序、搜索、解析语法等。递归的优点是代码简洁、易于理解,并...

Python内置函数range_python内置函数int的作用

range类型表示不可变的数字序列,通常用于在for循环中循环指定的次数。range(stop)range(start,stop[,step])range构造器的参数必须为整数(可以是内...

python常用得内置函数解析——abs()函数

大家号这两天主要是几个常用得内置函数详解详细解析一下Python中非常常用的内置函数abs()。1.函数定义abs(x)是Python的一个内置函数,用于返回一个数的绝对值。参数:x...

如何在Python中获取数字的绝对值?

Python有两种获取数字绝对值的方法:内置abs()函数返回绝对值。math.fabs()函数还返回浮点绝对值。abs()函数获取绝对值内置abs()函数返回绝对值,要使用该函数,只需直接调用:a...

贪心算法变种及Python模板_贪心算法几个经典例子python

贪心算法是一种在每一步选择中都采取当前状态下最优的选择,从而希望导致结果是全局最优的算法策略。以下是贪心算法的主要变种、对应的模板和解决的问题特点。1.区间调度问题问题特点需要从一组区间中选择最大数...

Python倒车请注意!负步长range的10个高能用法,让代码效率翻倍

你是否曾遇到过需要倒着处理数据的情况?面对时间序列、日志文件或者矩阵操作,传统的遍历方式往往捉襟见肘。今天我们就来揭秘Python中那个被低估的功能——range的负步长操作,让你的代码优雅反转!一、...

Python中while循环详解_python怎么while循环

Python中的`while`循环是一种基于条件判断的重复执行结构,适用于不确定循环次数但明确终止条件的场景。以下是详细解析:---###一、基本语法```pythonwhile条件表达式:循环体...

简单的python-核心篇-面向对象编程

在Python中,类本身也是对象,这被称为"元类"。这种设计让Python的面向对象编程具有极大的灵活性。classMyClass:"""一个简单的...

简单的python-python3中的不变的元组

golang中没有内置的元组类型,但是多值返回的处理结果模拟了元组的味道。因此,在golang中"元组”只是一个将多个值(可能是同类型的,也可能是不同类型的)绑定在一起的一种便利方法,通常,也...

python中必须掌握的20个核心函数——sorted()函数

sorted()是Python的内置函数,用于对可迭代对象进行排序,返回一个新的排序后的列表,不修改原始对象。一、sorted()的基本用法1.1方法签名sorted(iterable,*,ke...

12 个 Python 高级技巧,让你的代码瞬间清晰、高效

在日常的编程工作中,我们常常追求代码的精简、优雅和高效。你可能已经熟练掌握了列表推导式(listcomprehensions)、f-string和枚举(enumerate)等常用技巧,但有时仍会觉...

Python的10个进阶技巧:写出更快、更省内存、更优雅的代码

在Python的世界里,我们总是在追求效率和可读性的完美平衡。你不需要一个数百行的新框架来让你的代码变得优雅而快速。事实上,真正能带来巨大提升的,往往是那些看似微小、却拥有高杠杆作用的技巧。这些技巧能...