闭包实现数字相乘与任意数量数字相乘锁定函数NaN问题排查
解决闭包数字相乘与链式调用乘法函数问题
咱们先搞定你的两个需求,顺便修正你代码里导致NaN的bug~
一、先看你现有代码的问题(为什么会得到NaN)
你的代码里有几个关键错误:
- 参数名误用了
arguments:arguments是JavaScript函数内置的特殊对象,用来获取函数的所有参数,你把它当作自定义参数名,会覆盖内置的arguments,导致无法正确获取传入的参数。 - 索引参数的方式错误:
arguments.length是参数的个数(数字类型),你写arguments.length[i]相当于拿数字去索引,结果肯定是undefined,进而赋值给number后变成NaN。 - 没有累计乘积的逻辑:循环里只是反复给
number赋值最后一个参数,根本没有计算乘积。 - 缺少链式调用的核心逻辑:没有维护累计的结果,也没重写
toString/valueOf来返回最终结果。
二、需求1:闭包中实现数字相乘
闭包的核心是让内部函数能访问外部函数的变量,我们可以用闭包保存一个基数,返回的函数接收另一个数字并返回乘积:
// 创建一个乘法器,闭包保存基数base function createMultiplier(base) { // 内部函数可以访问外部的base变量 return function(num) { return base * num; }; } // 使用示例 const multiplyBy3 = createMultiplier(3); console.log(multiplyBy3(5)); // 输出15 console.log(multiplyBy3(7)); // 输出21
三、需求2:支持任意数量数字相乘的链式调用函数
要实现multiply(1)(2)(3)(4)(5) // 返回120这种效果,需要:
- 用闭包维护累计乘积
- 给返回的函数重写
toString方法(当需要隐式转换为字符串时,返回累计结果) - 支持每次调用传入单个或多个参数
正确实现代码:
function multiply(...args) { // 初始化累计乘积,先计算第一次传入参数的乘积 let total = args.reduce((acc, curr) => acc * curr, 1); // 定义用于链式调用的内部函数 const nextMultiplier = (...nextArgs) => { // 如果传入了新参数,累乘到total上 if (nextArgs.length > 0) { total *= nextArgs.reduce((acc, curr) => acc * curr, 1); return nextMultiplier; } // 没传参数时直接返回结果 return total; }; // 重写toString方法,当console.log或隐式转换时返回累计结果 nextMultiplier.toString = () => total; return nextMultiplier; } // 调用示例 console.log(multiply(1)(2)(3)(4)(5)); // 输出120 // 也支持单次传入多个参数 console.log(multiply(2, 3)(4)); // 输出24 // 直接调用单个参数也能返回结果 console.log(multiply(5)); // 输出5
原理说明:
- 每次调用
multiply或返回的nextMultiplier时,都会把传入的参数累乘到total上(闭包保存total,不会被销毁) - 当最后没有参数调用,或者需要打印结果时,JavaScript会隐式调用
toString方法,此时返回累计的total值,就能得到最终乘积。
内容的提问来源于stack exchange,提问作者Igor Shvets
相关产品推荐
相关产品推荐

