MST

星途 面试题库

面试题:JavaScript 高阶函数与函数式编程深度解析

在 JavaScript 中,基于高阶函数实现一个类似于 `lodash` 的 `curry` 函数。详细阐述函数式编程的特点,以及高阶函数在函数式编程中的核心地位,同时说明你实现的 `curry` 函数在实际项目中的应用场景和优势。
39.9万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

1. 实现类似于lodash的curry函数

function curry(func) {
    return function curried(...args) {
        if (args.length >= func.length) {
            return func.apply(this, args);
        } else {
            return function(...nextArgs) {
                return curried.apply(this, args.concat(nextArgs));
            };
        }
    };
}

2. 函数式编程的特点

  • 不可变数据:函数式编程强调数据的不可变性,避免直接修改数据,而是通过创建新的数据来反映变化。例如,在JavaScript中使用Object.assign或展开运算符来创建对象的副本。
let obj = { a: 1 };
let newObj = { ...obj, b: 2 };
  • 纯函数:纯函数是函数式编程的核心概念之一。纯函数对于相同的输入始终返回相同的输出,并且不产生副作用。例如:
function add(a, b) {
    return a + b;
}

这个函数无论何时调用,只要输入的ab相同,返回结果就相同,且不会改变外部状态。

  • 函数作为一等公民:在函数式编程中,函数可以像其他数据类型一样被传递、返回和赋值。例如:
function operate(a, b, func) {
    return func(a, b);
}
function multiply(a, b) {
    return a * b;
}
let result = operate(2, 3, multiply);

3. 高阶函数在函数式编程中的核心地位

  • 抽象和复用:高阶函数允许将通用的逻辑抽象出来,通过接受函数作为参数,实现复用。例如Array.prototype.map就是一个高阶函数,它接受一个函数作为参数,对数组中的每个元素应用该函数,从而实现对数组的转换操作,减少重复代码。
let numbers = [1, 2, 3];
let squared = numbers.map(num => num * num);
  • 函数组合:高阶函数可以用于实现函数组合,将多个小的函数组合成一个大的函数。例如:
function add1(x) { return x + 1; }
function multiply2(x) { return x * 2; }
function compose(...funcs) {
    return function(x) {
        return funcs.reduceRight((acc, func) => func(acc), x);
    };
}
let combined = compose(add1, multiply2);
let result = combined(3); // 先乘2再+1,结果为7

4. curry函数在实际项目中的应用场景和优势

应用场景

  • 参数复用:在一些场景下,部分参数是固定的,通过curry可以预先绑定这些参数。例如在日志记录中,日志级别可能大部分时候是固定的:
function log(level, message) {
    console.log(`[${level}] ${message}`);
}
let infoLog = curry(log)('info');
infoLog('This is an info log');
  • 函数组合curry后的函数更易于进行函数组合。因为每个函数都可以接受一个参数并返回一个新函数,便于将多个函数按照顺序组合起来。例如:
function add(x) { return function(y) { return x + y; }; }
function multiply(x) { return function(y) { return x * y; }; }
let addThenMultiply = compose(curry(multiply)(2), curry(add)(3));
let result = addThenMultiply(4); // 先3+4,再*2,结果为14

优势

  • 提高代码的可维护性和可测试性:由于curry函数基于纯函数,且通过参数复用和函数组合,使得每个函数的职责单一,更易于理解、维护和测试。
  • 灵活性:可以根据不同的需求动态地生成新的函数,而不需要编写大量重复的函数来适应不同参数组合的情况。