Подтвердить что ты не робот

Использование Javascript для привязки против карри?

Я пытаюсь понять разницу между curry vs bind.

Реализация bind:

/*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*/   }

Реализация curry:

/*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*/   };

Я уже знаю, что curry не является внутренней функцией (в отличие от bind, которая находится в IE9 +). Но все же:

Почему я слышу, как люди говорят о curry, хотя они могут просто использовать операцию bind?

Единственное различие - это контекст, который фактически найден только в функции bind.

различия

enter image description here

Пример:

Скажем, у меня есть эта функция:

function add(x,y,z)
{
  return x+y+z;
}

Я мог бы сделать это с помощью curry:

alert(add.curry(2).curry(1)(4)) //7

Но я мог бы также сделать это с помощью

alert(add.bind(undefined,2).bind(undefined,1)(4)) //7

Я не понимаю, почему эта функция термина curry существует, когда можно добавить фиктивный контекст к функции bind.

Что мне не хватает?

4b9b3361

Ответ 1

bind заставляет вас прикрепить контекст к функции, а при использовании curry вы можете отложить спецификацию контекста функции до тех пор, пока не будет вызывать функцию curries, полезную во многих случаях. < ш > рассмотрим следующий пример (не идеальный, просто чтобы проиллюстрировать идею):

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

Ответ 2

Есть разница в намерении.

Currying заключается в уменьшении количества аргументов, как правило, чтобы избежать многократного вызова функции с теми же начальными аргументами. Например:

var celsiusToKelvin = add.curry(273.15);

bind() - убедиться, что функция привязана к объекту. Кроме того, вы можете использовать средство currying, поэтому да, вы можете использовать bind() для curry(), но если вы хотите карри, curry() имеет меньше аргументов и показывает ваше намерение.

Ответ 3

Я думаю, что это связано с совместимостью со старыми браузерами, поскольку привязка доступна только с ECMAScript 5.

Посмотрите на список поддержки .bind(): http://kangax.github.io/es5-compat-table/

Также из того, что я слышал, большинство людей все еще используют curry, потому что оно выглядит более чистым, так как в аргументах не требуется лишний undefined.