【JavaScript】防抖、节流和函数柯理化

【JavaScript】防抖、节流和函数柯理化 专栏:JavaScript
个人主页:繁星学编程
个人简介:一个不断提高自我的平凡人
分享方向:目前主攻前端,其他知识也会阶段性分享
格言:☀️没有走不通的路,只有不敢走的人!☀️
让我们一起进步,一起成为更好的自己!!!

文章目录

  • 【JavaScript】防抖、节流和函数柯理化
    • 一. 函数柯理化
      • (1) 概念
      • (2) 案例:正则验证密码
      • (3) 函数柯理化的封装
    • 二. 函数防抖
    • 三. 函数节流
    • 四. 节流与防抖的区别是什么?

【JavaScript】防抖、节流和函数柯理化

一. 函数柯理化

(1) 概念

作用:把一次传递两个参数,变成两次每次传递一个参数

目的:利用闭包,把第一次传递的参数保存下来(延长变量的生命周期)

function add(num1) {
    return function (num2) {
        return num1 + num2;
    }
}
console.log(add(1));
/*
        ƒ (num2) {
                return num1 + num2;
            }
        */
console.log(add(1)(2)); // 3

(2) 案例:正则验证密码

方式一:判断正则写在函数内部,需要判断的值在函数外部测试

function testpw(str) {
    const reg = /^\w{6,12}$/;
    return reg.test(str);
}
const res1 = testpw("12345jfiang");
const res2 = testpw("jfiang");
console.log(res1, res2); // true true

方式二:正则和测试的值都在函数外部同时传入

function testpw(reg, str) {
    return reg.test(str);
}
const res1 = testpw(/^\w{6,12}$/, "1234");
const res2 = testpw(/^\w{6,12}$/, "1234fajin");
console.log(res1, res2); // false true

方式三:利用柯理化(闭包)封装

function testpw(reg) {
    return function (str) {
        return reg.test(str);
    }
}
const test1 = testpw(/^\w{6,12}$/);
const res1 = test1("1223");
console.log(res1); // false
// 生成一个验证手机号的函数
const testPhone = testpw(/^1\d{10}$/);
// 校验手机号
const res2 = testPhone('2341200');
const res3 = testPhone('12312345678');
console.log(res2, res3); // false true

(3) 函数柯理化的封装

函数柯理化封装

  1. 是多个参数互相利用

  2. 需要两个功能

    功能函数

    收集参数

功能:实现拼接地址栏

http://localhost:8080/a/b
	a : http 
	b : localhost
	c : 8080
	d : /a/b
功能函数 把 a b c d 拼接起来

// 并且要实现以下三种情况:
// 情况1
const res = curry(fn, 'http')
const res1 = res('localhost')
const res2 = res1('8080')
const res3 = res2('/a/b') // http://localhost:8080/a/b
console.log(res3);
// 情况2
// const res = curry(fn, 'http', 'localhost')
// const res1 = res('8080', '/a/b') // // http://localhost:8080/a/b
// 情况3
// const res = curry(fn, 'http', 'localhost', '8080', '/a/b')() // // http://localhost:8080/a/b
// console.log(res);

实现

function fn(a, b, c, d) {
    return a + '://' + b + ':' + c + d;
}
// 柯理化函数
function curry(fn, ...arg) {
    /*
    收集参数,判断参数的个数,够不够功能函数使用
    	如果够了:执行功能函数
    	如果不够:继续收集
    */
    // 对外部收集的参数进行处理
    let _arg = arg || []
    // 需要用_arg的length和 功能函数的参数个数进行比对

    // 获取函数形参的个数
    let len = fn.length
    return function (...arg) {
        _arg = [..._arg, ...arg]
        // 用处理好的参数进行数量判断
        if (_arg.length === len) {
            // 处理好的参数  ==== 功能函数参数相同
            return fn(..._arg)
        } else {
            // 处理好的参数<功能函数参数
            return curry(fn, ..._arg)
        }
    }
}
// const res = curry(fn)

二. 函数防抖

通过setTimeout的方式,在一定的时间间隔内,将多次触发变成一次触发。(通俗的说是在最后一次点击间隔规定时间之后才能再次成功触发,否则触发不成功)

<input type="text" id="ipt">
<!--  分割线 -->
ipt.oninput = function (e) {
    console.log(e.target.value);
}
// 每键入一次就会将input框中的value值输出

防抖的实现思路

  1. 在防抖函数返回的函数的上级作用域设置一个定时器变量t置为null;
  2. 通过t来判断是否是第一次执行。
  3. 如果不是第一次执行,清空定时器
  4. 如果是第一次执行,则通过进行代码执行.
  5. 最后设置定时器,规定时间之后将t设置为null,使得间隔时间之后t为null,间隔时间之后的点击变为第一次点击。

递进优化实现步骤

  • 第一步:简单实现

    let t = null;
    ipt.oninput = function () {
        clearInterval(t);
        t = setTimeout(() => {
            console.log(this.value);
        }, 1500);
    }
    // 一直键入值等待1.5s后输出最终值
    
  • 第二步:为了不污染全局,把变量放在函数里面

    ipt.oninput = (function () {
        let t = null;
        return function () {
            clearInterval(t);
            t = setTimeout(() => {
                console.log(this.value);
            }, 1500);
        }
    })()
    
  • 第三步:封装防抖函数

    function prevent(cb) {
        let t = null;
        return function () {
            clearInterval(t);
            t = setTimeout(() => {
                cb.call(this);
            }, 1500);
        }
    }
    ipt.oninput = prevent(function () {
        console.log(this.value);
    })
    

三. 函数节流

节流指的是减少一段时间内的触发频率。只有在上一次成功触发间隔规定时间之后,才能再次触发。

<input type="text" id="ipt">
<!--  分割线 -->
ipt.oninput = function (e) {
    console.log(e.target.value);
}
// 每键入一次就会将input框中的value值输出

节流的实现思路

  1. 在返回函数的上级作用域定义一个初始标记flag = false;
  2. 通过判断flag 是否=== true来确定是否已经触发
  3. 如果已经触发(flag === true),则中断函数
  4. 如果没有触发(flag === false),则让flag = false执行代码,执行后将flag = true

递进优化实现步骤

  • 第一步:简单实现

    let flag = false;
    ipt.oninput = function () {
        if (flag) return
        flag = true;
        setTimeout(() => {
            console.log(this.value);
            flag = false;
        }, 2500);
    }
    
  • 第二步:使用闭包

    ipt.oninput = (function () {
        let flag = false;
        return function () {
            if (flag) return
            flag = true;
            setTimeout(() => {
                console.log(this.value);
                flag = false;
            }, 2500)
        }
    })()
    
  • 第三步:封装

    function out(cb = () => { }) {
        let flag = false;
        return function () {
            if (flag) return
            flag = true;
            setTimeout(() => {
                cb.call(this);
                flag = false;
            }, 2500);
        }
    }
    ipt.oninput = out(function () {
        console.log(this.value);
    })
    

四. 节流与防抖的区别是什么?

  1. 防抖只在最后一次成功点击之后间隔规定时间之后才能再次成功触发,如果在时间间隔之内就被点击,需要重新间隔时间间隔才能点击。
  2. 节流则不同,节流只要在上一次成功触发规定时间之后点击就能再次触发,中间的触发不会产生影响。

结束语

希望对您有一点点帮助,如有错误欢迎小伙伴指正。
点赞:您的赞赏是我前进的动力!
⭐收藏:您的支持我是创作的源泉!
✍评论:您的建议是我改进的良药!
一起加油!!!

你可能感兴趣的:(JavaScript,javascript,前端,开发语言)