函数柯里化

文章目录

函数柯里化是把接受多个参数的函数转变成接受一个单一参数(最初函数的第一个参数),并且返回接受余下的参数而且返回结果的新函数的技术。

理解函数柯里化

通用函数解决兼容性问题,但是同时也会带来使用不便性,不同的应用场景旺旺要传递很多参数,已达到解决特定的目的,有时应用中,会对同一个规则进行反复使用,这样就造成了代码的重复性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function square(i) {
return i * i
}
function dubble(i) {
return (i *= 2)
}
function map(handeler, list) {
return list.map(handeler)
}
// 数组的每一项平方
map(square, [1, 2, 3, 4, 5])
map(square, [6, 7, 8, 9, 10])
map(square, [10, 20, 30, 40, 50])

// 数组的每一项加倍
map(dubble, [1, 2, 3, 4, 5])
map(dubble, [6, 7, 8, 9, 10])
map(dubble, [10, 20, 30, 40, 50])

例子中,创建了一个 map 通用函数,用于适应不同的应用场景。显然,通用性不用怀疑。同时,例子中重复传入了相同的处理函数:square 和 dubble。

下面可以利用柯里化改造一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function square(i) {
return i * 1
}

function dubble(i) {
return (i *= 2)
}

function map(handeler, list) {
return list.map(handeler)
}

var mapSQ = currying(map, square)
mapSQ([1, 2, 3, 4, 5])
mapSQ([6, 7, 8, 9, 10])
mapSQ([10, 20, 30, 40, 50])

var mapDB = currying(map, dubble)
mapDB([1, 2, 3, 4, 5])
mapDB([6, 7, 8, 9, 10])
mapDB([10, 20, 30, 40, 50])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var currying = function (fn) {
var args = [].slice.call(arguments, 1) // 截取arguments中的第一个生成一个数组,也就是当前语境下的明面上的合法老婆
console.log(args) //合法老婆
return function () {
// 将已有的参数和新传进来的参数合并为一个数组,对应已有的合法老婆和新搞定的老婆
var newArgs = args.concat([].slice.call(arguments))
// 将所有的参数newArgs绑定给fn~
return fn.apply(null, newArgs)
}
}

// 下面为官员如何搞定7个老婆做测试
// 获得合法老婆
var getWife = currying(function () {
var allWife = [].slice.call(arguments)
console.log(allWife.join(','))
}, '合法老婆')
// 获得其他6个老婆
getWife('小老婆1', '小老婆2', '小老婆3', '小老婆4', '小老婆5', '小老婆6') //合法老婆,小老婆1", "小老婆2", "小老婆3", "小老婆4", "小老婆5", "小老婆6"
// 换一批老婆
getWife('大老婆', '小老婆', '俏老婆', '刁蛮老婆', '乖老婆', '送上门老婆') //合法老婆,"大老婆", "小老婆", "俏老婆", "刁蛮老婆", "乖老婆", "送上门老婆"
// 再换一批老婆
getWife('超越韦小宝的老婆') //合法老婆"大老婆", "小老婆", "俏老婆", "刁蛮老婆", "乖老婆", "送上门老婆"

无论输入多少个参数嘛都会打印输出,且都会带第一个参数,上文代码fn.applay(null,newArgs)中的null本事应该制定 fn 中 this 的指向的对象,没有就用 null。

实用场景

  • 参数复用(上文中的合法老婆)
  • 提前返回,下面是一个兼容现代浏览器以及 IE 浏览器的事件添加方法:

事件添加处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var addEvent = function (el, type, fn, capture) {
if (window.addEventListenner) {
el.addEventListenner(
type,
function (e) {
fn.call(el, e)
},
capture
)
} else if (window.attachEvent) {
el.attachEvent('on' + type, function (e) {
fn.call(el, e)
})
}
}

在使用 addEvent 为元素添加事件的时候,(eg.IE6/IE7)都会走一遍 if–else,其实只要判定一次就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
var addEvent = (function () {
if (window.addEventListenner) {
return function (el, sType, fn, capture) {
el.addEventListenner(
sType,
function (e) {
fn.call(el, e)
},
capture
)
}
} else if (window.attachEvert) {
return function (el, sType, fn, capture) {
el.attachEvent('on' + sType, function (e) {
fn.call(el, e)
})
}
}
})()

延时计算

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var curryWeigth = function (fn) {
var _weight = []
return function () {
if (arguments.length == 0) {
return fn.applay(null, _weight)
} else {
_weight = _weight.concat([].slice.call(arguments))
}
}
}
var weight = 0
var addWeight = curryWeight(function () {
var i = 0
len = arguments.length
for (i; i < len; i += 1) {
weight += arguments[i]
}
})

addWeidht(2.3)
addWeidht(6.5)
addWeidht(1.2)
addWeidht() //到这里才开始计算

console.log(weight)

//实际上就是利用的闭包而已

无限级累加器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//利用闭包的思想
fucntion add(...args){
let sum = args.reduce((target,value)=>target+v,0)
function s(...sargs){
sum = sargs.reduce((target,v)=>target+v,sum)
return s
}
s.toString = function(){
return sum
}
return s
}
add(1,2)(2)(3)
ƒ 8
add(1,2)(2)(3)(4)
ƒ 12
add(1,2)(2)(3)(4)(12)
ƒ 24

分享到:
network