利用柯里化和闭包--实现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));

打印结果

总结

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

相关推荐
天天扭码7 分钟前
总所周知,JavaScript中有很多函数定义方式,如何“因地制宜”?(ˉ﹃ˉ)
前端·javascript·面试
一个专注写代码的程序媛12 分钟前
为什么vue的key值,不用index?
前端·javascript·vue.js
장숙혜23 分钟前
ElementUi的Dropdown下拉菜单的详细介绍及使用
前端·javascript·vue.js
火柴盒zhang26 分钟前
websheet之 编辑器
开发语言·前端·javascript·编辑器·spreadsheet·websheet
某公司摸鱼前端28 分钟前
uniapp 仿企微左边公司切换页
前端·uni-app·企业微信
WKK_31 分钟前
uniapp自定义封装tabbar
前端·javascript·小程序·uni-app
莫问alicia32 分钟前
react 常用钩子 hooks 总结
前端·javascript·react.js
Mintopia41 分钟前
图形学中的数学基础与 JavaScript 实践
前端·javascript·计算机图形学
Mintopia1 小时前
Three.js 制作飘摇的草:从基础到进阶的全流程教学
前端·javascript·three.js
BillKu1 小时前
Vue3父子组件数据双向同步实现方法
前端·javascript·vue.js