面试题答案
一键面试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;
}
这个函数无论何时调用,只要输入的a
和b
相同,返回结果就相同,且不会改变外部状态。
- 函数作为一等公民:在函数式编程中,函数可以像其他数据类型一样被传递、返回和赋值。例如:
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
函数基于纯函数,且通过参数复用和函数组合,使得每个函数的职责单一,更易于理解、维护和测试。 - 灵活性:可以根据不同的需求动态地生成新的函数,而不需要编写大量重复的函数来适应不同参数组合的情况。