在了解函数式编程之前,我们先看看命令式编程。
就像在英语中,命令式时态用于给出命令,编程中的命令式是给计算机一组语句来执行任务。
这些语句通常会改变程序的状态,例如更新全局变量,典型的例子就是写一个for
循环。
声明并定义一个变量,判断变量并循环遍历操作。相信很多同学在大一学C的时候对这一点深有体会了。
相反,函数式编程是声明式编程的一种形式,通过调用方法或函数来告诉计算机要做什么。
函数式编程中一个核心概念就是纯函数,如果一个函数满足以下几个条件,就可以认为这是个纯函数了:
- 它是一个函数;
- 当给定相同的输入(函数的参数)的时候,总是有相同的输出(返回值);
- 没有副作用;
- 不依赖于函数外部状态。
JavaScript 提供了许多处理常见任务的方法(API),所以我们不用写出计算机该如何执行它们。
例如,你可以用map
函数替代上面提到的for
循环来处理数组迭代。这有助于避免语义错误。
( map()函数的一个参数是自定义每一项遍历的形参名,另一参数为一个函数方法,返回一个新数组,
数组中的元素为原始数组元素调用函数处理后的值。通常情况下, map() 不会改变原始数组。)
当你在变量,数组或对象上调用一个普通函数,这个函数可能会改变对象中的变量或其他东西。
函数式编程的核心原则之一是不改变任何东西。变化会导致错误。如果一个函数不改变传入的参数、
全局变量等数据,那么它造成问题的可能性就会小很多。
函数式编程的另一个原则是:总是显式声明依赖关系。如果函数依赖于一个变量或对象,那么将该变量或对象作为参数直接传递到函数中。
这样做会有很多好处,其中一点是让函数更容易测试,因为你确切地知道参数是什么,并且这个参数也不依赖于程序中的任何其他内容。
其次,这样做可以让你更加自信(肆无忌惮)地更改,删除或添加新代码。因为你很清楚哪些是可以改的,哪些是不可以改的,这样你就知道哪里可能会有潜在的坑。
最后,无论执行哪一部分的代码,函数总是会为同一组输入生成相同的输出。
我们已经看到了函数式编程的两个原则:
- 不要更改变量或对象——创建新变量和对象,并在需要时从函数返回它们。
- 声明函数参数——函数内的任何计算仅取决于参数,而不取决于任何全局对象或变量。
当然,这只是函数式编程思想的冰山一角。
最近开始在学习React,官方给出的 React 的核心理念是:
A JavaScript library for building user interfaces.
即专注于构建 View
层的一个库。React
的核心开发者之一的 Sebastian Markbåge 认为:
UI
只是把数据通过映射关系变成另一种形式的数据。给定相同的输入(数据)必然会有相同的输出(UI
),即一个简单的纯函数。
UI = f (state),这也是React 中的函数式思想的具体体现