JS - 函数柯里化

发布时间:2023年12月19日

1,什么是柯里化 Curry

简单来说,柯里化技术是为了扁平化处理多参数的函数,提高函数的适用性。

实现逻辑:把一个多参数的目标函数,变成接受部分参数的函数,同时该函数用来接收目标函数的剩余参数。

柯里化是 js 闭包特性的经典使用场景。

举例:

function add(x, y) {
  return x + y;
}
console.log(add(1, 2)); // 3

柯里化后:

function add(x) {
  return function (y) {
    return x + y;
  }
}
console.log(add(1)(2)); // 3

2,实践和应用

1,参数复用

将相同的参数固定下来。

// eg: 正则验证字符串 reg.test(txt)

// 函数封装后
function check(reg, txt) {
  return reg.test(txt)
}

// 即使是相同的正则表达式,也需要重新传递一次
console.log(check(/\d+/g, 'test1')); // true
console.log(check(/\d+/g, 'testtest')); // false
console.log(check(/[a-z]+/g, 'test')); // true

// 柯里化后
function curryingCheck(reg) {
  return function (txt) {
    return reg.test(txt)
  }
}

// 正则表达式通过闭包保存了起来
var hasNumber = curryingCheck(/\d+/g)
var hasLetter = curryingCheck(/[a-z]+/g)

console.log(hasNumber('test1')); // true
console.log(hasNumber('testtest'));  // false
console.log(hasLetter('21212')); // false

2,参数复用2

实现效果如下,具体参考这篇文章 element-plus 架构 - BEM和命名空间

const ns = useNamespace('button')
ns.b() // el-button
ns.b('group') // el-button-group
ns.m('primary') // el-button--primary
ns.em('text', 'expand') // el-button__text--expand
ns.is('disabled', true) // is-disabled

3,提前确认

元素绑定事件的工具函数,参考 element-ui 的源码

export const on = (function() {
  if (!isServer && document.addEventListener) {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.addEventListener(event, handler, false);
      }
    };
  } else {
    return function(element, event, handler) {
      if (element && event && handler) {
        element.attachEvent('on' + event, handler);
      }
    };
  }
})();

注意到 on 是立即执行函数,执行后返回一个新函数,这样会提前确认用哪个方法,避免每次都做判断。

3,手动简单实现

实现细节:curry 工具函数 curry 接受的参数个数不确定,但第一个参数一定是目标函数fn,剩下的参数是目标函数原本的参数 ...argscurry 的返回值也是一个函数_curry,用来接受目标函数剩下的参数。

并且在调用_curry时,会判断传递给_curry 的参数个数 + 之前传递给 curry 的参数个数之和,是否满足目标函数的个数。

如果是,则执行原本的目标函数;否则继续调用 _curry 并传递目标函数剩下的参数。

function curry(fn, ...args) {
  // 函数的 length 是函数的参数个数
  if (args.length === fn.length) {
    return fn(...args)
  }

  return function _curry(...params) {
    args.push(...params)
    if (args.length === fn.length) {
      return fn(...args)
    }
    return _curry
  }
}

function add(a, b, c) {
  return a + b + c
}

console.log(curry(add, 1, 2, 3)) // 6
console.log(curry(add, 1)(2)(3)) // 6
console.log(curry(add)(1)(2)(3)) // 6

以上。

文章来源:https://blog.csdn.net/qq_40147756/article/details/135068333
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。