JS的防抖,节流,柯里化和反柯里化

Posted 一只菜鸟攻城狮啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JS的防抖,节流,柯里化和反柯里化相关的知识,希望对你有一定的参考价值。

节流

定义

将高频率事件转变为低频率事件

实现

定时器实现

实现思路:当触发事件的时候,我们设置一个定时器,再次触发事件的时候,如果定时器存在,就不执行,直到delay时间后,定时器执行执行函数,并且清空定时器,这样就可以设置下个定时器。当第一次触发事件时,不会立即执行函数,而是在delay秒后才执行。而后再怎么频繁触发事件,也都是每delay时间才执行一次。当最后一次停止触发后,由于定时器的delay延迟,还会执行一次函数。

var throttle = function(func, delay) {            
    var timer = null;            
    return function() {                
        var context = this;               
        var args = arguments;                
        if (!timer) {                    
            timer = setTimeout(function() {                        
                func.apply(context, args);                        
                timer = null;                    
            }, delay);                
        }            
    }        
}

时间戳实现

实现思路:使用事件戳来计算时间,时间差大于delay则执行

var throttle = function(func, delay) {            
  var prev = Date.now();            
  return function() {                
    var context = this;                
    var args = arguments;                
    var now = Date.now();                
    if (now - prev >= delay) {                    
      func.apply(context, args);                    
      prev = Date.now();                
    }            
  }        
}

应用场景

  • 鼠标不断点击触发,mousedown(单位时间内只触发一次)
  • 监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断

防抖

定义

将高频事件只在最后一次进行触发。即不关心中间过程,只注重结果

实现

实现思路:利用定时器,触发时不停清空上一个定时器,只有当不触发时才会执行函数fn

function debounce(fn, wait) {    
    var timeout = null;    
    return function() {        
        if(timeout !== null)   clearTimeout(timeout);        
        timeout = setTimeout(fn, wait);    
    }
}

应用场景

  • search输入框,在输入完之后请求接口
  • 页面滚动特定距离 显示【返回顶部按钮】
  • 页面resize 触发事件

柯里化

定义

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

特性

  • 提高了代码的合理性,更重的它突出一种思想---降低适用范围,提高适用性
  • 对于一个已有函数,对其约定好其中的某些参数输入,然后生成一个更有好的、更符合业务逻辑的函数。
  • 提高针对性
  • 延迟执行(只有在最后一次才执行)
  • 固定易变因素

实现

实现思路:利用闭包,只要由参数就保存参数,并返回函数,无参数时则执行

  function add() {
    //建立args,利用闭包特性,不断保存arguments,注意arguments是个对象
    // 注意JS中的Array.prototype.slice.call(arguments)能将有length属性的对象转换为数组(特别注意: 这个对象一定要有length属性).
    var args = Array.prototype.slice.call(arguments);
    var _add = function() {
        if (arguments.length === 0){
            //参数为空,对args执行加法
            return args.reduce(function(a,b){return a+b});
        } else {
            //否则,保存参数到args,返回一个函数
            args = args.concat(Array.prototype.slice.call(arguments))
            return _add;
        }
    }
    //返回_add函数
    return _add;
  }

反柯里化

定义

在与扩大函数的适用性,使本来作为特定对象所拥有的功能的函数可以被任意对象所用.简单来说就是函数的借用,使函数能够接受处理其他对象,通过借用泛化、扩大了函数的使用范围。

实现

Function.prototype.uncurrying = function() {
  var self = this;
  return function() {
    var obj = Array.prototype.shift.call(arguments);
    return self.apply(obj, arguments);
  };
};
更简便的写法
Function.prototype.uncurrying = function() {
  var self = this;
  return function() {
    return Function.prototype.call.apply(self,arguments)
  };
}

详解链接

以上是关于JS的防抖,节流,柯里化和反柯里化的主要内容,如果未能解决你的问题,请参考以下文章

节流函数&防抖函数 柯里化函数

js反柯里化个人理解以及操作

js 基础 源码学习 柯里化和箭头函数

关于柯里化函数

Scala - 柯里化和默认参数

java8入门必备—函数式编程思维——函数式语言向语言和运行时让渡控制权的途径——柯里化和函数的部分施用