函数式编程
介绍
函数式编程是一种基于函数计算的软件开发方法。像数学一样,函数在编程中通过输入产生输出。你可以通过多种方式组合基本功能来构建越来越复杂的程序。
函数式编程遵循几个核心原则:
- 独立于程序状态或全局变量,只依赖于传递给它们的参数进行计算
- 限制更改程序状态,避免更改保存数据的全局对象
- 对程序的副作用尽量小
函数式编程式将程序分成小的、可测试的部分,这里介绍 JavaScript 中函数式编程的基本原则。
术语
首先,我们将介绍一些术语:
Callbacks
是被传递到另一个函数中调用的函数。你应该已经在其他函数中看过这个写法,例如在filter
中,回调函数告诉 JavaScript 以什么规则过滤数组。
函数就像其他正常值一样,可以赋值给变量、传递给另一个函数,或从其它函数返回,这种函数叫做first class
函数。在 JavaScript 中,所有函数都是first class
函数。
将函数为参数或返回值的函数叫做higher order
函数。
当函数传递给另一个函数或从另一个函数返回时,那些传入或返回的函数可以叫做lambda
。
Array.splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
函数式编程注意
函数不要改变外部变量(避免避免突变和副作用)
1
2
3
4
5
6
7
8
9// 全局变量
var fixedValue = 4;
function incrementer () {
return fixedValue + 1; //这行
}
var newValue = incrementer(); // 应等于 5
console.log(fixedValue); // 应打印 4
传递参数,避免外部依赖
1
2
3
4
5
6
7
8
9// 全局变量
var fixedValue = 4;
function incrementer (value) { // < ==
return value + 1;
}
var newValue = incrementer(fixedValue); // 应等于 5
console.log(fixedValue); // 应打印 4目前为止,我们已经看到了函数式编程的两个原则:
1) 不要更改变量或对象——创建新变量和对象,并在需要时从函数返回它们。
2) 声明函数参数——函数内的任何计算仅取决于参数,而不取决于任何全局对象或变量。
添加一个元素到数组最后
1 | function add (arr,bookName) { |
注意:不能直接返回return newArr.push(bookName);
因为这样函数返回值是添加元素后数组的长度。
1 | //添加末尾元素精简版: |
1 | //删除特定元素: |
常用函数
- Array.push() 添加元素到数组末尾,返回添加后数组长度
- Array.splice() 添加、删除数组元素
- Array.filter() 返回满足回调函数的数组元素组成的新数组(即筛除不符合的元素)
- Array.map() 返回每个数组元素调用回调函数后的结果组成的新数组,只要回调函数不改变原数组则原数组不变。
- Array.slice() 返回一个新数组,不会修改原数组 用slice代替splice可以避免改变原数组
使用map方法代替for循环遍历数组是个好方法。
Array.concat() 返回拼接后的数组
Array.sort() 对数组进行排序,如果该方法时没有参数,将按字母顺序也就是按照字符编码的顺序进行排序,数字排序加参数,a,b 返回a-b则升序,返回a<b则降序。
sort方法会产生改变原始数组中元素顺序的副作用。换句话说,它会改变数组的位置。避免这种情况的一种方法是先将空数组连接到正在排序的数组上(记住
concat
返回一个新数组),再用sort
方法。1
2
3
4
5
6
7
8var globalArray = [5, 6, 3, 2, 9];
function nonMutatingSort(arr) {
var newArr=[];
return newArr.concat(arr).sort(function(a,b){
return a-b;
});
}
nonMutatingSort(globalArray);
split() 分割字符串成为数组 ,下面是以字符串的符号作为分割点进行分割
1
2
3
4
5function splitify(str) {
return str.split(/[\ |\~|\`|\!|\@|\#|\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\||\\|\[|\]|\{|\}|\;|\:|\"|\'|\,|\<|\.|\>|\/|\?]/g) //过于复杂
//应该简化 return str.split(/\W/)
}
console.log(splitify("Hello World,I-am code")); //["Hello","world","I","am","code"]join() 将数组组合成字符串 把数组中的所有元素放入一个字符串,并通过指定的分隔符参数进行分隔。
every() 检查每个数组元素是否符合条件。
1
2
3
4
5
6function checkPositive(arr) {
return arr.every(function(val){
return val>0;
});
}
checkPositive([1, 2, 3, -4, 5]);//返回truesome() 检查数组中是否有元素符合给定的条件
1
2
3
4
5var numbers = [10, 50, 8, 220, 110, 11];
numbers.some(function(currentValue) {
return currentValue < 10;
});
// 返回 true
字符串转换为URL片段
许多内容管理站点(CMS)为了让添加书签更简单,会将帖子的标题添加到 URL 上。举个例子,如果你写了一篇标题为 “Stop Using Reduce” 的帖子,URL很可能会包含标题字符串的某种形式 (如:”…/stop-using-reduce”)
转换字符串title
带有连字符号的 URL 版本。
要求:
输入包含空格和标题大小写单词的字符串
输出字符串,单词之间的空格用连字符(-
)替换
输出应该是小写字母
输出不应有任何空格
1 | var globalTitle = "Winter Is Coming"; |
函数柯里化
arity
是函数所需的形参的数量。函数Currying
意思是把接受多个arity
的函数变换成接受单一arity
的函数。
换句话说,就是重构函数让它接收一个参数,然后返回接收下一个参数的函数,依此类推。
1 | //Un-curried function |
1 | function add(x) { |