如何在JavaScript中实现支持多轮链式调用的闭包求和?
Great question! Your initial closure works perfectly for two arguments, but extending it to handle arbitrary chained calls (like sum(2)(3)(4)...(100)) just needs a small tweak to how we handle the return value and value coercion.
The Core Idea
The key is to make the returned function both callable (for chaining) and able to resolve to the total sum when needed. We can do this by leveraging JavaScript's valueOf method—this method is automatically called when an object (and yes, functions are objects!) is converted to a primitive value.
Implementation
Here's a robust solution that supports any number of chained calls:
function sum(initialNum) { let total = initialNum; // Define the function that will handle subsequent calls const addNext = function(nextNum) { total += nextNum; return addNext; // Return itself to enable chaining }; // Override valueOf to return the total when coerced to a primitive addNext.valueOf = function() { return total; }; // Optional: Override toString for string coercion (e.g., when concatenating with strings) addNext.toString = function() { return String(total); }; return addNext; }
How It Works
- Initialization: When you call
sum(2), we initializetotalto 2 and return theaddNextfunction. - Chained Calls: Each time you call
addNextwith a new number (likesum(2)(3)), we add that number tototaland returnaddNextagain—so you can keep chaining indefinitely. - Getting the Result: When you need the final sum (e.g.,
console.log(sum(2)(3)(4))), JavaScript tries to convert theaddNextfunction to a primitive value. Our customvalueOfmethod kicks in and returns the accumulatedtotal.
Testing It Out
Try these examples to see it in action:
console.log(sum(2)(3)); // Outputs 5console.log(sum(2)(3)(4)); // Outputs 9const total = sum(1)(2)(3)...(100); // Calculates the sum from 1 to 100console.log(total); // Outputs 5050
Bonus: ES6 Arrow Function Version
If you prefer a more concise syntax, here's an ES6 variant:
const sum = initialNum => { let total = initialNum; const addNext = nextNum => { total += nextNum; return addNext; }; addNext.valueOf = () => total; return addNext; };
This works exactly the same way—just a shorter, modern take on the same logic.
内容的提问来源于stack exchange,提问作者naveen

