Javascript 可以说是即支持面向对象也支持函数编程,使用函数式编程在 Javascript非常重要,对于函数式编程,有些重要的概念需要了解。
闭包
闭包是 Javascript 重要知识点,也是函数式编程中的重点,什么是闭包?闭包的概念很简单,就是访问作用域,闭包可以访问全局变量,也可以访问外层函数定义的变量或者外层函数的参数。访问全局变量很好理解,函数都可以访问全局变量,访问外层函数变量和外层函数的参数,这个是闭包的核心。闭包怎么创建的,函数返回一个函数,那么它就是闭包。英文是 Closure, 可以这么理解,你要关闭一个函数,所有他能访问的变量都要记住。几个应用场景,便于理解:
创建一个简单的闭包,这个特别简单,理解一下概念,返回函数中的函数:
function createGreeting(greeting) {
return function(name) {
console.log(greeting + ', ' + name);
};
}
访问外层函数的变量,这里就可以看到闭包的用处了,封装了数据,对外层函数的数据进行了修改。
function createCounter() {
let count = 0; // This is a private variable
return {
increment: function() {
count++;
return count;
},
decrement: function() {
count--;
return count;
}
};
}
const counter = createCounter();
console.log(counter.increment()); // 1
console.log(counter.increment()); // 2
console.log(counter.decrement()); // 1
纯函数
纯函数指的是一个函数,其返回值仅依赖于其接收的参数,并且该函数在执行过程中不会产生任何副作用。简单理解就是数学公式 y = 2x,他不会就修改外部的任何变量,当 x 值固定时,y 的结果也是固定的,不会因为调用次数的不同而导致结果不同。为什么要用纯函数呢,主要是能减少 bug,减少不确定性的影响。项目中最怕的是什么,刚开始开发都挺好的,UAT 开始可能就有问题了,按下葫芦起了瓢,当然可以通过充分测试来发现问题。但是如果开始就让影响减少,每次改动我们就有底气了,不是吗?而且随着函数式组件、Hooks 的流行,用纯函数写法也成为了最佳实践,React 官网就明确说要写纯组件。
举个反例,来自React 官网,函数式组件修改全局变量。
let guest = 0;
function Cup() {
// Bad: changing a preexisting variable!
guest = guest + 1;
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup />
<Cup />
<Cup />
</>
);
}
修改的版本,通过参数传递,这样不会影响
function Cup({ guest }) {
return <h2>Tea cup for guest #{guest}</h2>;
}
export default function TeaSet() {
return (
<>
<Cup guest={1} />
<Cup guest={2} />
<Cup guest={3} />
</>
);
}
高阶函数
高阶函数是一个既接受函数作为参数,也返回函数的函数。这个可以举个例子就是 React 的 Hoc 组件,有点继承的那个意思。
柯里化
柯里化是一种在计算机科学和数学中使用的技术,它涉及将接受多个参数的函数转换成一系列只接受一个参数的函数。每个新函数都返回另一个函数,直到所有原始参数都被处理,然后执行最终的计算并返回结果。例如 sum(a, b),可以转换为 curry(sum)(a)(b)。主要作用是预先指定某些参数,拿日志举个例子
# 创建一个日志方法
const loggerHelper = (mode,initialMessage,errorMessage,lineNo)
# 定义好前两个参数,生成 3 个新的方法
let errorLogger = curryN(loggerHelper)("ERROR")("Error At Stats.js");
let debugLogger = curryN(loggerHelper)("DEBUG")("Debug At Stats.js");
let warnLogger = curryN(loggerHelper)("WARN")("Warn At Stats.js");
//for error
errorLogger("Error message",21)
//for debug
debugLogger("Debug message",233)
//for warn
warnLogger("Warn message",34)
偏函数
偏函数(Partial Function)是一个计算机科学中的概念,它指的是通过固定一个或多个参数来创建一个新的函数的行为。柯里化必须从左到右有序的,而偏函数,可以固定任意参数。
function helloUser(username, str, str1){
console.log(username,str, str1)
}
let a1 = _.partial(helloUser, _, 'zzzz', _)
a1('a', "c")
运行结果是 a zzzz c
以上这些是函数式编程的主要特性,最重要的就是纯函数和闭包,其他的都可以理解为语法糖。