JavaScript -函数式编程

本文介绍了JavaScript中的函数式编程概念,包括头等函数和高阶函数。详细讲解了如何在函数中避免全局变量的修改,使用map、filter、slice、concat、reduce、sort、split、join、every和some等方法操作数组。此外,还讨论了函数柯里化和局部调用的概念,以及它们在函数式编程中的应用。

头等 first class 函数 高阶 ( higher order) 函数

Callbacks 是被传递到另一个函数中调用的函数。
函数就像其他正常值一样,可以赋值给变量、传递给另一个函数,或从其它函数返回,这种函数叫做头等 first class 函数。
将函数为参数或返回值的函数叫做高阶 ( higher order) 函数
当函数被传递给另一个函数或从另一个函数返回时,那些传入或返回的函数可以叫做 lambda。

在函数式编程中,改变或变更叫做 mutation,这种改变的结果叫做“副作用”(side effect)。 理想情况下,函数应该是不会产生任何副作用的 pure function。

在函数中重构全局变量

不要更改变量或对象 - 创建新变量和对象,并在需要时从函数返回它们。 提示:使用类似 var newArr = arrVar 时 arrVar 是一个数组,代码只是创建一个对现有变量的引用,而不是副本。 所以更改 newArr 中的值会同时更改 arrVar 中的值。

声明函数参数 - 函数内的任何计算仅取决于参数,而不取决于任何全局对象或变量。

let newArr = [...arr]; // Copy the bookList array to a new array.
使用 map 方法从数组中提取数据 Array.prototype.map()

在对每个元素应用回调函数后,它会创建一个新数组(不改变原来的数组)。 它这样做时没有改变原始数组。

const users = [
  { name: 'John', age: 34 },
  { name: 'Amy', age: 20 },
  { name: 'camperCat', age: 10 }
];

const names = users.map(user => user.name);
console.log(names);
将显示值 [ 'John', 'Amy', 'camperCat' ]
使用 filter 方法从数组中提取数据

filter 接收一个回调函数,将回调函数内的逻辑应用于数组的每个元素,新数组包含根据回调函数内条件返回 true 的元素。 换言之,它根据传递给它的函数过滤数组。 和 map 一样,filter 不会改变原始数组。

const users = [
  { name: 'John', age: 34 },
  { name: 'Amy', age: 20 },
  { name: 'camperCat', age: 10 }
];

const usersUnder30 = users.filter(user => user.age < 30);
console.log(usersUnder30); 
将显示值 [ { name: 'Amy', age: 20 }, { name: 'camperCat', age: 10 } ]
使用 slice 方法返回数组的一部分

slice 返回一个新数组,不会修改原始数组

var arr = ["Cat", "Dog", "Tiger", "Zebra"];
var newArray = arr.slice(1, 3);
newArray 值为 ["Dog", "Tiger"]
使用 slice 而不是 splice 从数组中移除元素

splice 方法会改变调用它的原始数组
slice 方法不会改变原始数组,而是返回一个可以保存到变量中的新数组
使用 slice 方法替代 splice 有助于避免数组变化产生的副作用

使用 concat 方法组合两个数组

对数组来说,在一个数组上调用 concat 方法,然后提供另一个数组作为参数添加到第一个数组末尾。 它返回一个新数组,不会改变任何一个原始数组。

[1, 2, 3].concat([4, 5, 6]);
返回的数组将是 [1, 2, 3, 4, 5, 6]
使用 concat 而不是 push 将元素添加到数组的末尾

push会改变原数组,concat不会

使用 reduce 方法分析数据

reduce方法遍历数组中的每个项目并返回单个值(即字符串、数字、对象、数组)

const users = [
  { name: 'John', age: 34 },
  { name: 'Amy', age: 20 },
  { name: 'camperCat', age: 10 }
];

const usersObj = users.reduce((obj, user) => {
  obj[user.name] = user.age;
  return obj;
}, {});
console.log(usersObj);
控制台将显示值 { John: 34, Amy: 20, camperCat: 10 }
使用 sort 方法按字母顺序给数组排序

sort 方法会产生改变原始数组中元素顺序

function ascendingOrder(arr) {
  return arr.sort(function(a, b) {
    return a - b;
  });
}
ascendingOrder([1, 5, 2, 3, 4]);
这将返回值 [1, 2, 3, 4, 5]return a-b 这段代码:a指的是array[j] b指的是array[j+1] 即 a 指的是前一个数,b指的是后一个数;
a-b>0时,也就是 第一个数比第二个数大 则 在if语句中 fncompare()函数的结果 为>0
所以if语句可以执行,两个数交换位置 a 数 换到 b 的位置 意思是 :大的数向后移动
所以 return a-b 的结果就是正序(因为将大的数向后排)
同理 可以知道 return b-a 就是倒序。

function reverseAlpha(arr) {
  return arr.sort(function(a, b) {
    return a === b ? 0 : a < b ? 1 : -1;
  });
}

reverseAlpha(['l', 'h', 'z', 'b', 's']);
这将返回值 ['z', 's', 'l', 'h', 'b']。

JavaScript 的默认排序方法是 Unicode 值顺序排序,有时可能会
得到意想不到的结果。 因此,建议提供一个回调函数来指定如何对
数组项目排序。 这个回调函数通常叫做 compareFunction,它根据 
compareFunction 的返回值决定数组元素的排序方式: 如果两个元
素 a 和 b,compareFunction(a,b) 返回一个比 0 小的值,那么 a 
会在 b 的前面。 如果两个元素 a 和 b,compareFunction(a,b) 
返回一个比 0 大的值,那么 b 会在 a 的前面。 如果两个元素 a 
和 b,compareFunction(a,b) 返回等于 0 的值,那么 a 和 b 的
位置保持不变
使用 split 方法将字符串拆分成数组
var str = "Hello World";
var bySpace = str.split(" ");

var otherString = "How9are7you2today";
var byDigits = otherString.split(/\d/);
bySpace 将有值 ["Hello", "World"],byDigits 将有值 ["How", "are", "you", "today"]
使用 join 方法将数组组合成字符串
var arr = ["Hello", "World"];
var str = arr.join(" ");
使用 every 方法检查数组中的每个元素是否符合条件

如果所有元素满足条件,返回布尔值 true,反之返回 false

检测数组 numbers 的所有元素是否都小于 10
var numbers = [1, 5, 8, 0, 10, 11];
numbers.every(function(currentValue) {
  return currentValue < 10;
});
使用 some 方法检查数组中是否有元素是否符合条件

如果有一个元素满足条件,返回布尔值 true,反之返回 false

var numbers = [10, 50, 8, 220, 110, 11];
numbers.some(function(currentValue) {
  return currentValue < 10;
});
函数柯里化和局部调用

arity(参数个数)是函数所需的形参的数量。 函数柯里化(Currying)意思是把接受多个 arity 的函数变换成接受单一 arity 的函数
换句话说,就是重构函数让它接收一个参数,然后返回接收下一个参数的函数,依此类推

function unCurried(x, y) {
  return x + y;
}

function curried(x) {
  return function(y) {
    return x + y;
  }
}

const curried = x => y => x + y

curried(1)(2)
curried(1)(2) 会返回 3

局部调用( partial application)的意思是一次对一个函数应用几个参数,然后返回另一个应用更多参数的函数
function impartial(x, y, z) {
return x + y + z;
}
var partialFn = impartial.bind(this, 1, 2);
partialFn(10); // 13

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值