纯函数
说明
意思是调用的函数不依赖外部的变量,比如调用foo(111) ,不管在哪里调用,return出来的都是一样的,而不是根据外部环境不一样导致不一样。
副作用见下,就是不能对外部产生影响
副作用
案例
var names = ["abc", "cba", "nba", "dna"]
// slice只要给它传入一个start/end, 那么对于同一个数组来说, 它会给我们返回确定的值
// slice函数本身它是不会修改原来的数组
// slice函数本身就是一个纯函数
var newNames1 = names.slice(0, 3)
console.log(newNames1)
console.log(names)
// ["abc", "cba", "nba", "dna"]
// splice在执行时, 有修改掉调用的数组对象本身, 修改的这个操作就是产生的副作用
// splice不是一个纯函数
var newNames2 = names.splice(2)
console.log(newNames2)
console.log(names)
修改对象属性,只能通过返回新对象的方式,不影响原对象
优势
===================
柯理化
说明
// 柯里化
// 只传递 toUpOrLow() 这个函数的1个参数upOrLow来调用它,
// 然后它返回另一个函数,来处理剩余参数str
function toUpOrLow(upOrLow){
if(upOrLow == "up"){
return function(str){
return str.toUpperCase()
}
}else if(upOrLow == "low"){
return function(str){
return str.toLowerCase()
}
}
}
console.log(toUpOrLow("up")("aBc")) // "ABC"
console.log(toUpOrLow("low")("aBc")) // "abc"
某些情况可以通过箭头函数简化
作用1:函数的职责单一
作用2:复用
转成柯理化
// 普通函数
function log(date, type, message) {
console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]: [${message}]`)
}
// 柯里化函数的实现hyCurrying
function hyCurrying(fn) {
function curried(...args) {
// 判断当前已经接收的参数的个数, 可以参数本身需要接受的参数是否已经一致了
// 1.当已经传入的参数 大于等于 需要的参数时, 就执行函数
if (args.length >= fn.length) {
// fn(...args)
// fn.call(this, ...args)
return fn.apply(this, args)
} else {
// 没有达到个数时, 需要返回一个新的函数, 继续来接收的参数
function curried2(...args2) {
// 接收到参数后, 需要递归调用curried来检查函数的个数是否达到
return curried.apply(this, args.concat(args2))
}
return curried2
}
}
return curried
}
// 普通函数,转成柯理化
var curryAdd = hyCurrying(add1)
console.log(curryAdd(10, 20, 30))
console.log(curryAdd(10, 20)(30))
console.log(curryAdd(10)(20)(30))
使用场景
Vue源码,很多高级的库里面有用到,可以自己定制化一些实现(比如自定义渲染器),然后传入柯理化的函数,增加可拓展性
===================
组合函数
说明
两个函数
正常调用
组合调用
通用的组合函数
function fnCompose(...fns) {
// 获取传入函数的数量
var length = fns.length
// 1、先判断传入的是不是函数
for (var i = 0; i < length; i++) {
if (typeof fns[i] !== 'function') {
throw new TypeError("Expected arguments are functions")
}
}
// 定义组合函数
function compose(...args) {
var index = 0
// 调用第一个函数
var result = length ? fns[index].apply(this, args): args
// 如果还有其他函数,就依次调用
while(++index < length) {
result = fns[index].call(this, result)
}
return result
}
// 最后返回出去调用
return compose
}