这篇文章解释了在JavaScript中解currying和currying的应用程序。它是由一个tweet布兰登·艾希的。
要理解什么是uncurrening,以及它为什么有用,我们首先需要看看泛型方法。
// Simplified version of the actual implementation: Array.prototype.forEach = function (callback) { for(var i=0; i<this.length; i++) { if (i in this) { callback(this[i], i); } } };这可以被认为是forEach()的隐式参数。forEach()与任何this参数一起工作,这些参数可以执行以下任务。
function printArgs() { Array.prototype.forEach.call(arguments, function (elem, index) { console.log(index+". "+elem); }); }call()比forEach()多一个参数:它的第一个参数是this的值。互动:
> printArgs("a", "b") 0. a 1. bJavaScript中有几个方法是通用的,它们大多在Array.prototype。
obj.method(arg1, arg2)给一个签名
method(obj, arg1, arg2)当一个方法被常规应用时,取消currying允许你使它变得更漂亮。示例:
Array.forEach = Array.prototype.forEach.uncurryThis(); function printArgs() { Array.forEach(arguments, function (elem, index) { console.log(index+". "+elem); }); }有一个proposal用于在ECMAScript的未来版本中对所有数组方法执行此操作。以下是实现uncurrythis的三种方法。
版本1:真正发生的是什么[作者:艾希,略有修改]?
Function.prototype.uncurryThis = function () { var f = this; return function () { var a = arguments; return f.apply(a[0], [].slice.call(a, 1)); }; };版本2:函数的未修改版本与在原始函数上调用call()方法相同。我们可以通过bind()借用该方法:
Function.prototype.uncurryThis = function () { return this.call.bind(this); };版本3:最好定义标准方法,而不太依赖外部方法。此外,在ECMAScript5之前,bind()不存在。因此,我们将第2版重写如下。
Function.prototype.uncurryThis = function () { var f = this; return function () { return f.call.apply(f, arguments) }; };上面的代码仍然是“借用call()方法”的脉络。
var obj = { method: function (arg) { var self = this; // let nested function access `this` someFunction(..., function() { self.otherMethod(arg); }); }, otherMethod: function (arg) { ... } }你会写
var obj = { method: function (self, arg) { // additional argument `self` someFunction(..., function() { self.otherMethod(arg); }); }.curryThis(), // introduce an additional argument otherMethod: function (arg) { ... } }我们把隐式参数this变成了显式参数self。换句话说:我们已经从一个动态的这个变成了一个词汇上的自我。如果这始终是一个显式参数,JavaScript会更简单。
实现curryThis():
Function.prototype.curryThis = function () { var f = this; return function () { var a = Array.prototype.slice(arguments); a.unshift(this); return f.apply(null, a); }; };