到底JS柯里化在项目中怎么用?

4,669 阅读3分钟

前言

[适合读者]:有一定开发经验的前端人员

之前在很多文章里面看了柯里化的相关知识,大多举的例子都是实现累加累乘这些的函数,然后具体项目里面怎么用,实际场景很少提到,总感觉看完之后好像理解了,又好像没理解,可能主要还是没有一个实际的真实运用场景导致我们理解起来很困难,接下来我尝试写一些柯里化在项目中的运用希望能帮助大家理解这个东西

柯里化

下面先说说柯里化的几个特点,然后根据这几个特点分别举例来说明一下实际运用场景

  1. 提前返回
  2. 延迟执行
  3. 参数复用

提前返回

案例一(常见的兼容性判断代码)
  1. 封装一个addEvent兼容低版本IE的代码

这个是一个提前返回的经典案例,通过一个自执行函数来将if...else...判断只执行一次,并返回了一个新的函数,那么后续再次调用的时候就不会执行if...else...的判断了,提升了代码性能。

      var addEvent = (function() {
        if (window.addEventListener) {
          return function(el, type, cb, bubbing) {
            el.addEventListener(
              type,
              function(e) {
                cb.call(el, e);
              },
              bubbing
            );
          };
        } else if (window.attachEvent) {
          return function(el, type, cb, bubbing) {
            el.attachEvent('on' + type, function() {
              cb.call(el, e);
            });
          };
        }
      })();

  1. 封装一个简单的createXmlHttpRequest 方法

这个的原理同上

    var createXmlHttpRequest = (function() {
        var xmlHttp;
        if (window.XMLHttpRequest) {
          return function() {
            return new XMLHttpRequest();
          };
        } else if (window.ActiveXObject) {
          return function() {
            return new ActiveXObject('Msxml2.XMLHTTP');
          };
        }
      })();

通过上述两个案例,我们可以发现提前执行大多数场景应该是用在我们需要对不同终端做兼容处理的场景上面,那么总结下要触发提前执行这个场景,需要满足如下两个条件:

  1. 函数中需要使用if...else...或者其他的分支判断
  2. 返回结果是一个新的函数,而不是一个具体的值

注: 使用柯里化返回结果是一个值而不是函数的话个人觉得不太需要使用

延迟执行

案例一 (节流防抖函数)
  1. 封装一个防抖函数,节流函数也是同样的延迟执行的道理
    function debuonce(fn, time) {
        let timer;
        return function() {
          const _args = [].slice.call(arguments);
          clearTimeout(timer);
          timer = setTimeout(() => {
            fn.apply(this, _args);
          }, time);
        };
      }
案例二(bind函数)
  1. 封装一个bind函数 bind方法的作用是对象冒充,改变函数的作用域,但是和call和apply的区别就是其返回值是一个函数,并且调用后并不执行这个函数,下面是一个bind函数的简单示例,未考虑new的情况。

详细的bind函数可以参照这篇文章:www.cnblogs.com/moqiutao/p/…

    Function.prototype.bind = function(fn) {
        const args = [].slice.call(arguments, 1);
        const context = this;
        return function() {
          const _args = args.concat([].slice.call(arguments, 1));
          return context.apply(fn, _args);
        };
      };

通过上述案例可以看出,一般触发延迟执行场景,需要以下两个条件:

  1. 返回一个新函数
  2. 新函数里面有上面引用了外层函数作用域中的变量

参数复用

这个情况可以参考网上的累加累乘这些案例

总结

函数柯里化确实比较难懂,初学者需要大量实践才能够明白其中的原委,虽然柯里化会有一定的性能问题,不过大多数人的代码里面性能问题基本上不会是因为使用了柯里化导致的,所以可以放心使用。

本篇先写这些案例,后续会继续补充相关案例~

如果读者还有一些实际案例,欢迎留言,我会对文章进行修改补充~

参考文章

JS中的柯里化(currying):www.zhangxinxu.com/wordpress/2…

学会函数柯里化(curry):www.codercto.com/a/54607.htm…