currification - Usos de Javascript de bind vs curry?
currying es6 (3)
Estoy tratando de entender la diferencia entre curry
vs bind
.
La implementación de bind
es:
/*1*/ Function.prototype.bind = function ()
/*2*/ {
/*3*/ var fn = this,
/*4*/ args = Array.prototype.slice.call(arguments);
/*5*/ var object = args.shift();
/*6*/ return function ()
/*7*/ {
/*8*/ return fn.apply(object,
/*9*/ args.concat(Array.prototype.slice.call(arguments)))
/*10*/ };
/*11*/ }
La implementación del curry
es:
/*1*/ Function.prototype.curry = function ()
/*2*/ {
/*3*/ var fn = this,
/*4*/ args = Array.prototype.slice.call(arguments);
/*5*/ return function ()
/*6*/ {
/*7*/ return fn.apply(this,
/*8*/ args.concat(Array.prototype.slice.call(arguments)));
/*9*/ };
/*10*/ };
Ya sé que el curry
no es una función interna (a diferencia de bind
que está en IE9 +). Pero aún:
¿Por qué escucho a la gente seguir hablando de curry
, mientras que simplemente pueden usar la operación de bind
?
La única diferencia es el contexto que en realidad se encuentra solo en la función de bind
.
Ejemplo:
Digamos que tengo esta función:
function add(x,y,z)
{
return x+y+z;
}
Yo podría hacerlo con curry
:
alert(add.curry(2).curry(1)(4)) //7
Pero también podría hacerlo con:
alert(add.bind(undefined,2).bind(undefined,1)(4)) //7
No entiendo por qué existe esta función de término de curry
, mientras que es posible agregar un contexto ficticio a la función de enlace.
Qué me estoy perdiendo ?
Creo que tiene algo que ver con la compatibilidad con navegadores antiguos, ya que el enlace solo está disponible desde ECMAScript 5.
Vea esto para obtener una lista de .bind()
: http://kangax.github.io/es5-compat-table/
Además, por lo que he escuchado, la mayoría de la gente todavía usa curry porque se ve más limpio, ya que no necesita ese extra undefined
en los argumentos.
Hay una diferencia en la intención.
Currying es reducir el número de argumentos, generalmente para evitar llamar mucho a una función con los mismos argumentos iniciales. Por ejemplo:
var celsiusToKelvin = add.curry(273.15);
bind() es para asegurarse de que una función está asociada a un objeto. También sucede que ofrece una facilidad de curry, así que sí, puedes usar bind () para curry (), pero si quieres curry, curry () tiene menos argumentos y muestra tu intención.
bind
obliga a adjuntar un contexto a la función, mientras que mediante el uso de curry
, puede retrasar la especificación del contexto de la función hasta que invoque la función curry, lo que es útil en muchos casos.
Considere el siguiente ejemplo (no el perfecto, solo para ilustrar la idea):
function Query(sessionKey, dataBuilder) {
this.sessionKey = sessionKey;
this.url = "http://www.example.com/search";
this.dataBuilder = dataBuilder
this.search = function (term) {
$.ajax({
type: "POST",
url: this.url,
data: this.dataBuilder(term);
})
}
}
function dataBuilder(entity, query) {
var payload = JSON.stringify({
''entity'': entity,
''searchTerm'': query
''session'': this.sessionKey // will be always undefined if bind(undefined,...) is used
});
return payload
}
var bindEx= dataBuilder.bind(undefined, "username");
var curryEx= dataBuilder.curry("username");
var usernameQuery = new Query("id1234",bindEx); // won''t work, this.sessionKey will be undefined
usernameQuery = new Query("id1234",curryEx); // will work, this.sessionKey will be id1234 in the DataBuilder