进击的加法:从简单加法到柯里化加法的进阶之路

275 阅读4分钟

前言

何为加法?自然是两数相加,但是今天我要讲点不一样的加法,由浅入深,从普通加法到科里化加法,不断升级加法的形态,从无垢巨人的初级形态,成为进击的巨人吧!!

正文

无垢的加法

欢迎来到无垢的世界!

说到加法第一想到的那肯定是a+b=c,于是我们就有了以下代码

function add(a, b){  
    return a + b;
}

但是这要写未免简陋了点,这里面还是有一些小小问题的,万一输入的参数不够呢?万一数据类型有问题呢?于是就有了

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

现在就优雅许多了,当我们到达这个最初级的加法形式,我们就已经成为了初级的小无垢了

可是如果我们一次给的参数不够只能一次给一部分怎么办?或者说我想可以三个、四个、甚至更多数相加呢?没办法,目前的你是实现不了的,毕竟你现在只是个小小无垢,这对于你来说还是太困难了,看来我们得继续升级了。

这个时候就出现了新写法-闭包,无垢加点脑

进击的加法

给我们的小无垢加点脑后,终于我们来到了智慧巨人的世界

现在我们要去实现无垢无法实现的问题了

这也便是柯里化的思想,把一个多参数的函数逐步拆分成多个单参数的函数组合

实现这个的话我们要使用闭包

什么是闭包呢?

闭包是一个函数,这个函数能够访问并记住它周围环境(包括外部函数)的变量,即使这个外部函数已经执行完毕。闭包"闭合"了函数内部和外部的变量作用域。

文字可能有点抽象,那我们直接上代码

function outerFunction() {
  let count = 0;

  function innerFunction() {
    count++;
    console.log("Count is:", count);
  }

  return innerFunction;
}

const myFunction = outerFunction();
myFunction(); // Count: 1
myFunction(); // Count: 2
myFunction(); // Count: 3

相信通过这段代码大家一定懂了什么是闭包了吧,那么我们的加法就开始进行升级了

  • 实现可以三个、四个、甚至更多数相加
function add(x) {
    return function (y) {
        return x + y;
    }
}
console.log(add(1)(2)); // 3
console.log(add(1)(2)(3)); // 6
console.log(add(1)(2)(3)(4)); // 10
  1. add 函数接受一个参数 x,并返回一个新的函数。
  2. 返回的这个新函数也接受一个参数 y,并返回 x + y 的结果。
  3. 当我们调用 add(1) 时,它会返回一个新的函数。这个新函数"记住"了 x 的值为 1
  4. 当我们继续调用返回的函数,比如 add(1)(2),它会把 y 的值设置为 2,并返回 x + y,也就是 1 + 2 = 3
  5. 同理,add(1)(2)(3) 会返回 1 + 2 + 3 = 6add(1)(2)(3)(4) 会返回 1 + 2 + 3 + 4 = 10

这样的写法可以实现多个数不断相加

  • 实现将函数参数分批给
const curry = (fn, ...args) =>
    // console.log(args.length, fn.length);
    args.length >= fn.length ? fn(...args):(..._args) => curry(fn, ...args, ..._args)

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

const curryAdd = curry(add,1)
const curryAdd1 = curryAdd(2)
const curryAdd2 = curryAdd1(3)
console.log(curryAdd2(4)); // 10

console.log(curry(add,1)(2)(3)(3)); // 9
  1. curry 函数接受两个参数:

    • fn: 需要柯里化的原函数
    • ...args: 传递给 fn 的初始参数列表
  2. 在 curry 函数内部,我们首先检查当前传递的参数 args 是否已经足够调用原函数 fn

    • 如果参数足够,我们就直接调用 fn 并返回结果。
    • 如果参数不够,我们返回一个新的函数,该函数会递归调用 curry,并将当前参数和新传入的参数合并起来。

经过升级,终于我们成功成为了一个合格的进击巨人!!!

总结

本文深入探讨了 JavaScript 中闭包和函数柯里化的概念及其应用,为读者提供了实践和理解这些重要编程技巧基础。让一个小无垢最终成为了进击巨人