📅  最后修改于: 2023-12-03 14:43:32.172000             🧑  作者: Mango
JavaScript是一种高级编程语言,主要用于在网页上为用户提供动态交互体验。与其他编程语言不同的是,JavaScript也被视为一种函数式编程语言。这篇文章将介绍JS是如何函数式编程的。
在JS中,函数被看作是第一类对象(First-Class Object),也就是说它和其他的数据类型一样,可以用来赋值给变量,作为函数参数和返回值。
函数作为变量:
let greet = function(name) {
console.log('Hello ' + name + '!');
};
greet('Alice'); // Hello Alice!
函数作为参数:
let add = function(a, b) {
return a + b;
};
let calculator = function(opr, a, b) {
return opr(a, b);
};
console.log(calculator(add, 2, 3)); // 5
函数作为返回值:
let getReminderFn = function(divisor) {
return function(dividend) {
return dividend % divisor;
};
};
let reminderOf5 = getReminderFn(5);
console.log(reminderOf5(12)); // 2
高阶函数(Higher-Order Function)是指接受一个或多个函数作为参数,并且/或者返回一个函数的函数。
例如, map()
、filter()
和 reduce()
都是高阶函数,它们接受一个函数作为参数。
let a = [1, 3, 5, 7, 9];
let squares = a.map(function(x) {
return x * x;
});
console.log(squares); // [1, 9, 25, 49, 81]
let a = [1, 3, 5, 7, 9];
let evens = a.filter(function(x) {
return x % 2 == 0;
});
console.log(evens); // []
let a = [1, 3, 5, 7, 9];
let sum = a.reduce(function(acc, val) {
return acc + val;
});
console.log(sum); // 25
在函数式编程中,纯函数是指不对外部状态做任何更改,并且对于相同的输入总是返回相同的输出的函数。
例如,函数 reverse()
并不是纯函数,因为它会改变输入数组。而函数 slice()
就是一个纯函数,因为它只是返回输入数组的子数组,并不改变原数组。
纯函数具有以下优点:
编译器可以对尾部递归函数进行优化,使得它们在运行时只占用一个堆栈帧。这样可以避免栈溢出的问题,使得递归函数在不增加内存负担的情况下可以处理更多的数据。
下面是一个朴素的阶乘实现:
function factorial(n) {
if (n === 0) {
return 1;
} else {
return n * factorial(n - 1);
}
}
console.log(factorial(5)); // 120
该实现是非尾递归的。在计算5!的时候,调用栈的深度为5。如果n的值非常大,那么递归的深度也将迅速增加,可能会导致栈溢出的问题。
现在,我们可以使用尾调用优化将其转化为尾递归实现:
function factorial(n, acc = 1) {
if (n === 0) {
return acc;
} else {
return factorial(n - 1, acc * n);
}
}
console.log(factorial(5)); // 120
由于 factorial()
最后一步只是返回同样的函数调用,并且它不会增加栈的深度,所以这个实现是尾递归的。在计算5!的时候,调用栈的深度仅为1。