了解JavaScript函数式编程目录
什么是声明式,我们将不再指示计算机如何工作,而是指我们明确希望得到的结果。这种编程方式会改变我们习以为常的命令式编程相比,会让我们的轻松许多。
和命令式不同,声明式意味着我们要写表达式,而不是一步一步的指示。
// 命令式
var makes = [];
for (i = 0; i < cars.length; i++) {
makes.push(cars[i].make);
}
// 声明式
var makes = cars.map(function(car){ return car.make; });
复制代码
命令式的循环要求你必须先实例化一个数组,而且执行完这个实例化语句之后,解释器才继续执行后面的代码。然后再直接迭代 cars
列表,手动增加计数器,把各种零零散散的东西都展示出来...实在是直白得有些露骨。
使用 map
的版本是一个表达式,它对执行顺序没有要求。而且,map
函数如何进行迭代,返回的数组如何收集,都有很大的自由度。它指明的是做什么,不是怎么做。因此,它是正儿八经的声明式代码。
// 命令式
var authenticate = function(form) {
var user = toUser(form);
return logIn(user);
};
// 声明式
var authenticate = compose(logIn, toUser);
复制代码
看过前面文章的朋友应该明白 compose 组合代码的意义。
虽然命令式的版本并不一定就是错的,但还是硬编码了那种一步接一步的执行方式。而 compose 表达式只是简单地指出了这样一个事实:用户验证是 toUser 和 logIn 两个行为的组合。这再次说明,声明式为潜在的代码更新提供了支持,使得我们的应用代码成为了一种高级规范(high level specification)。
声明式最重要的是不是指定执行顺序,所以它天然的适合进行并行运算。它和纯函数一起解释了为何函数式编程是未来并行计算的一个不错的选择 -- 我们真的不需要做什么就能现实一个并行/并发系统。
如果函数或表达式修改程序的某些状态(除了返回值之外)在其自身范围之外或具有与其调用函数或外部的可观察变量,则称其具有副作用。
let meetup = {name:'JS',isActive:true,members:49};
const scheduleMeetup = (date, place) => {
meetup.date = date;
meetup.place = place;
if (meetup.members < 50)
meetup.isActive = false;
}
const publishMeetup = () => {
if (meetup.isActive) {
meetup.publish = true;
}
}
scheduleMeetup('today','Bnagalore');
publishMeetup();
console.log(meetup);
复制代码
上面的这个程序有副作用,因为函数scheduleMeetup
的实际职责是添加 date
和 place
,但它正在修改 isActive
的值以及其他一些函数 publishMeetup
所依赖的值,以及 publishMeetup
函数将作为副作用没有所需的输出,因为它的输入在两者之间发生了变化。在程序)中,调试副作用会变得非常困难。
声明式和命令式的区别和含义,这里我们可以结合上一篇文章 组合代码 相关知识。