# 07-函数柯里化

# 定义

"柯里化",就是把一个多参数的函数,转化为单参数函数。

# 柯里化适用场景

  • 不方便传入参数的时候
// 回调函数需要传入参数的时候: 
function callback (b) {

}
// 使用callback作为回调函数,并需要传入参数的情况,使用bind对其柯里化
Promise.resolve().then(callback.bind(this, 'param'))
1
2
3
4
5
6
  • 函数的很多参数是固定的
// 部分参数固定的情况:柯里化后只需传入剩余参数即可
function inputCheck(reg, value) {}
const numberCheck = inputCheck.bind(this, /^[0-9]*$/);
numberCheck(2);
1
2
3
4

# 柯里化实现

  • 柯里化函数会接收到固定参数,然后在柯里化函数里面,返回一个新的函数,接收剩余参数
function currying(a) {
    return function (b) {
      return a + b;
    };
  }
currying(1)(2); // 3

1
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

# 手写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