利用柯里化和闭包--实现add函数

前言

什么是柯里化?

柯里化就是将一个接收多个参数的函数,转化为多个函数,每个函数都只接收一个参数并返回一个新的函数,直到所有参数都被提供完毕。

示例

手写一个 add 函数实现两数相加

javascript 复制代码
function add(a, b) {
    if(arguments.length < 2) {
        console.log('参数不足');
        return
    }
    // 数据类型, 参数数量的问题
    if(typeof a != 'number' || typeof b != 'number') {
        console.log('类型错误');
        return
    }
    return a + b;
}

console.log(add(1, 2));
console.log(add(1, '2'));
console.log(add(1));

打印结果

还可利用闭包完成一个add,实现分布接收参数,一次只接收一个参数

javascript 复制代码
function add(a) {
    // 第一个参数a
    return function(b) {
        return a + b;
    }
}

console.log(add(2)(4));

打印结果

分析

add函数执行完成后,会返回一个匿名函数function,function执行完要返回 a + b的值,由于a是add函数的值,function要用到a的值,所以add在执行完毕后会生成一个闭包里面存放了a的值,function会在这个闭包里寻找a的值,最后做加法运算并返回值。

如果参数不定,该如何实现?

对于es5,函数内置了一个arguments对象,它包含了传给该函数的所有参数,可以通过arguments[i]来访问这些参数。

javascript 复制代码
const curry = function (fn) {
    // 参数对象
    for (let i = 0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
}
function add(x, y, z, m) {
    return x + y + z + m;
}

curry(add, 1, 2, 3)

打印结果

对于es6,为了让代码更加简洁,引入了 ...args rest运算符,其能够接收任意数量的参数,并将它们以数组的形式收集起来。

javascript 复制代码
const curry = (fn, ...args) => {
    console.log(args);
}
function add(x, y, z, m) {
    return x + y + z + m;
}

curry(add, 1, 2, 3)

打印结果

注: 如果使用了箭头函数 arrow function ,又去使用了es5 里面的arguments,由于箭头函数里面没有arguments,违反了es6 简洁的原则,所以应该用rest 运算符

柯里化的思路:

定义一个curry函数,用于将add函数需要的参数逐个传入,并且需要一个判断语句 args.length >= fn.length ? fn(...args) :(..._args) => curry(fn, ...args, ..._args),如果传入的参数大于或者等于fn所需要的参数个数,则执行fn(...args),将...args所接收到的所有参数传给fn;否则,执行(..._args) => curry(fn, ...args, ..._args),返回一个新的柯里化函数,..._args继续接收参数,并且将已有的参数...args与新参数进行合并,再递归调用curry函数,直到接收到的参数足够调用fn。

php 复制代码
const curry = (fn, ...args) => 
    args.length >= fn.length
    ? fn(...args)
    :(..._args) => curry(fn, ...args, ..._args)

// 原函数
// 柯里化,慢慢收集参数
const add = (x, y, z, m) => {
    return x + y + z + m
}

console.log(curry(add, 1)(2)(3)(4));

打印结果

总结

快去自己手搓一个柯里化函数,实现逐个传参。

相关推荐
别拿曾经看以后~34 分钟前
【el-form】记一例好用的el-input输入框回车调接口和el-button按钮防重点击
javascript·vue.js·elementui
我要洋人死37 分钟前
导航栏及下拉菜单的实现
前端·css·css3
川石课堂软件测试40 分钟前
性能测试|docker容器下搭建JMeter+Grafana+Influxdb监控可视化平台
运维·javascript·深度学习·jmeter·docker·容器·grafana
科技探秘人1 小时前
Chrome与火狐哪个浏览器的隐私追踪功能更好
前端·chrome
科技探秘人1 小时前
Chrome与傲游浏览器性能与功能的深度对比
前端·chrome
JerryXZR1 小时前
前端开发中ES6的技术细节二
前端·javascript·es6
七星静香1 小时前
laravel chunkById 分块查询 使用时的问题
java·前端·laravel
q2498596931 小时前
前端预览word、excel、ppt
前端·word·excel
小华同学ai1 小时前
wflow-web:开源啦 ,高仿钉钉、飞书、企业微信的审批流程设计器,轻松打造属于你的工作流设计器
前端·钉钉·飞书
problc1 小时前
Flutter中文字体设置指南:打造个性化的应用体验
android·javascript·flutter