能否在JavaScript中实现Currying function constructor:new Class()(param1)(...)形式柯里化?
Absolutely! You can totally pull off this constructor currying pattern in JavaScript. Let’s look at two practical approaches to make var o = new Class()(param1)(param2)(...) work as expected.
方法1:构造函数返回柯里化函数
This approach has your constructor return a dedicated currying function that collects arguments over chained calls, while still giving you direct access to the actual instance.
function Class() { // Store all arguments collected from chained calls const collectedArgs = []; // The currying function that handles each invocation const curriedFn = function(...args) { collectedArgs.push(...args); // Return the function itself to keep the chain alive return curriedFn; }; // Create your core instance with custom properties/methods const instance = { // Example method to use collected arguments logArgs() { console.log('Collected arguments:', collectedArgs); }, // Getter to safely access the argument list get args() { return [...collectedArgs]; } }; // Attach the instance's features to the currying function // So you can interact with the instance directly from the chained result Object.assign(curriedFn, instance); return curriedFn; }
使用示例:
var o = new Class()('param1')('param2', 'param3'); o.logArgs(); // Logs: Collected arguments: ["param1", "param2", "param3"] console.log(o.args); // Outputs: ["param1", "param2", "param3"]
关键说明:
- The constructor builds both the core instance and the currying function.
- Every
(param)call adds arguments to the collection and returns the function to maintain chaining. Object.assignlets you access the instance’s methods/properties directly without extra steps.
方法2:用Proxy让实例可调用
Plain JavaScript objects can’t be invoked like functions, but we can use a Proxy to wrap the instance and intercept function calls—enabling the chained syntax seamlessly.
function Class() { // Your instance with internal state and logic const instance = { _args: [], get args() { return [...this._args]; }, init() { // Use collected arguments to initialize the instance console.log('Initializing with:', this._args); } }; // Proxy wrapper to handle function call operations const instanceProxy = new Proxy(instance, { apply(target, thisArg, args) { // Add incoming arguments to the instance's collection target._args.push(...args); // Return the proxy to keep chaining calls return instanceProxy; } }); return instanceProxy; }
使用示例:
var o = new Class()('first')('second')('third'); console.log(o.args); // Outputs: ["first", "second", "third"] o.init(); // Logs: Initializing with: ["first", "second", "third"]
关键说明:
- The Proxy acts as a middleman: when you call
(param), theapplytrap catches the invocation, updates the instance’s state, and returns the proxy to continue chaining. - All non-call operations (like accessing properties or methods) are forwarded directly to the underlying instance, so you interact with it just like a normal object.
小提醒
If you need to explicitly end currying and return the raw instance, you can add a check (e.g., return the instance when no arguments are passed to a call). Both approaches work in modern browsers and Node.js—Proxy is only unsupported in legacy environments like IE.
内容的提问来源于stack exchange,提问作者Alphapage

