反柯里化的核心目的是解除方法与特定对象的绑定,实现泛化this绑定和方法借用;它将obj.method(...)转为method(obj, ...),使Array.prototype等内置方法可作用于任意兼容对象。

反柯里化的核心目的不是“还原柯里化函数”,而是解除方法与特定对象的绑定关系,让原本只能在某个原型上使用的实例方法(比如 Array.prototype.push、Array.prototype.slice),变成可被任意对象调用的通用函数。它本质上是泛化 this 绑定,实现方法借用。
理解关键转换:从 obj.method(...) 到 method(obj, ...)
JavaScript 中很多内置方法设计为“只属于某类对象”,例如:
-
[1,2].push(3)——push必须在数组上调用 -
arguments.slice(1)—— 报错!因为arguments不是数组,没有slice方法
反柯里化后,就能写成:
-
push(arr, 3)——arr可以是任何带length和可索引属性的对象 -
slice(arguments, 1)—— 直接对类数组调用,无需.call冗余写法
标准实现方式:基于 Function.prototype.call
最简洁可靠的写法是利用 call 的能力:把第一个参数作为 this,其余参数传给原函数:
function uncurry(fn) {
return function(obj, ...args) {
return fn.call(obj, ...args);
};
}
使用示例:
const slice = uncurry(Array.prototype.slice);slice({0: 'a', 1: 'b', length: 2}, 1); // ['b']slice(arguments, 0); // 安全处理 arguments
更紧凑的写法(一行解决)
借助 bind 和 call 的组合,可省去显式函数声明:
const push = Function.prototype.call.bind(Array.prototype.push); const slice = Function.prototype.call.bind(Array.prototype.slice);
原理:bind 固定 call 的第一个参数为 Array.prototype.push,之后每次调用 push(obj, ...args) 实际执行的是 Array.prototype.push.call(obj, ...args)。
实际能泛化的常见方法
以下原型方法通过反柯里化后,即可脱离原对象类型限制:
-
Array.prototype.push→ 支持向类数组添加元素 -
Array.prototype.slice→ 转换类数组为真数组或截取 -
Array.prototype.indexOf→ 在任意带索引和length的对象中查找 -
String.prototype.split→ 对任意有toString()的值调用 -
Object.prototype.toString→ 安全判断类型:toString(obj)比obj.toString()更鲁棒
注意:并非所有方法都适合反柯里化。若方法内部强依赖自身构造逻辑(如 new Date().toISOString()),脱离实例上下文可能失效。

















