# 07-函数柯里化
# 定义
"柯里化",就是把一个多参数的函数,转化为单参数函数。
# 柯里化适用场景
- 不方便传入参数的时候
// 回调函数需要传入参数的时候:
function callback (b) {
}
// 使用callback作为回调函数,并需要传入参数的情况,使用bind对其柯里化
Promise.resolve().then(callback.bind(this, 'param'))
1
2
3
4
5
6
2
3
4
5
6
- 函数的很多参数是固定的
// 部分参数固定的情况:柯里化后只需传入剩余参数即可
function inputCheck(reg, value) {}
const numberCheck = inputCheck.bind(this, /^[0-9]*$/);
numberCheck(2);
1
2
3
4
2
3
4
# 柯里化实现
- 柯里化函数会接收到固定参数,然后在柯里化函数里面,返回一个新的函数,接收剩余参数
function currying(a) {
return function (b) {
return a + b;
};
}
currying(1)(2); // 3
1
2
3
4
5
6
7
2
3
4
5
6
7
- 通用柯里化函数
function curry(func) {
//得到从下标1开始的参数
var args = Array.prototype.slice.call(arguments, 1);
var that = this;
return function () {
var curArgs = Array.from(arguments); //当前调用的参数
var totalArgs = args.concat(curArgs);
if (totalArgs.length >= func.length) {
//参数数量够了
return func.apply(null, totalArgs);
}
else {
//参数数量仍然不够
totalArgs.unshift(func);
return that.curry.apply(that, totalArgs);
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 手写bind函数
// 手写实现call 函数,传入参数为参数列表
Function.prototype.myCall = function (thisArg, ...args) {
// 调用者必须是函数
if (typeof this !== 'function') {
throw new Error('not a function');
}
// 判断是node还是浏览器环境
if (thisArg === undefined || thisArg === null) {
thisArg = typeof window === undefined ? global : window;
}
// 包装一下
thisArg = Objec(thisArg);
//在指定的thisArg上添加方法,使用symbol可以避免覆盖了thisArg的同名方法/属性。
let key = Symbol('fn');
thisArg[key] = this;
//先将结果保存起来
let result = thisArg[key](...args);
//删除在thisArg上添加的方法,回到最初的样子
delete thisArg[key];
return result;
}
// 手写实现apply 函数: 传入参数为数组
Function.prototype.myApply = function (thisArg,args) {
if(typeof this !== 'function') throw new Error('Not a Function');
if(thisArg ===null || thisArg === undefined) {
thisArg = typeof window === 'undefined'? global:window;
}
thisArg = Object(thisArg);
let key = Symbol('fn');
thisArg[key] = this;
let result = thisArg[key](...args);
delete thisArg[key];
return result;
}
// 函数柯里化,手写bind函数
Function.prototype.myBind = function (thisArg) {
if(typeof this !== 'function') throw new Error('Not a Function');
if(thisArg ===null || thisArg === undefined) {
thisArg = typeof window === 'undefined'? global:window;
}
let _self = this;
let args = Array.prototype.slice.call(arguments, 1);
return function(){
return _self.apply(thisArg, args.concat(Array.prototype.slice.call(arguments)));
}
}
var arr = [1, 11, 5, 8, 12];
var max = Math.max.bind(null, arr[0], arr[1], arr[2], arr[3]);
console.log(max(arr[4])); //12
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55