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

JavaScript частично примененная функция - Как привязать только второй параметр?

Извините, если мне не хватает чего-то очевидного, но я не могу понять, как связать определенный (n-й) аргумент функции в javascript. Большинство моих функциональных программ, которые я узнал, были от Scala, поэтому я не уверен, что это возможно даже в JS.

Например, я понимаю, что я могу сделать следующее, чтобы связать 1-й аргумент

var add = function (a, b) {
   return a + b;
};

add(1, 3); //returns 4

var addThree = add.bind(null, 3);  //this = null.  a = 3
addThree(4);                        //returns 7

Но как я могу привязать второй аргумент и оставить первый как есть. Другими словами, как я могу привязать только к "b"?

Из того, что я могу сказать из mozilla - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind, аргументы фактически вложены, что делает его похожим на то, что он должен быть определен заказ? (Я очень, возможно, читаю это неправильно)

Изменить: Я понимаю, что это своего рода надуманный пример. Я просто пытаюсь учиться, если я в конечном итоге займусь чем-то более сложным, чем добавлением 2 чисел. Я также пытаюсь понять, как аргументы bind() фактически работают под капотом.

4b9b3361

Ответ 1

Конечно, вы можете это сделать. Здесь решение ES6 с использованием оператора спреда (...), так как оно немного компактнее.

// Bind arguments starting after however many are passed in.
function bind_trailing_args(fn, ...bound_args) {
    return function(...args) {
        return fn(...args, ...bound_args);
    };
}

Если вы предпочитаете указывать позицию начала привязки:

// Bind arguments starting with argument number "n".
function bind_args_from_n(fn, n, ...bound_args) {
    return function(...args) {
        return fn(...args.slice(0, n-1), ...bound_args);
    };
}

В ES5 вам нужно гадать с построением списков аргументов.

// ES5 version: construct arguments lists yourself
function bind_trailing_args(fn) {
    var bound_args = [].slice.call(arguments, 1);
    return function() {
        var args = [].concat.call(arguments, bound_args);
        return fn.apply(this, args);
    };
}

В отличие от первых двух примеров, этот дескриптор правильно обрабатывает this.

В контексте вашего примера:

var addThree = bind_trailing_args(add, 3);
addThree(1) // calls add(1, 3)

Вы также можете рассмотреть возможность использования одной из библиотек функционального программирования, доступных для JS, например http://osteele.com/sources/javascript/functional/. Вещь, которую вы хотите, называется rcurry там.

Ответ 2

Вы можете использовать lodash _.bind, чтобы достичь этого:

var add = function(a, b) {
  document.write(a + b);
};

// Bind to first parameter (Nothing special here)
var bound = _.bind(add, null, 3);
bound(4);
// → 7

// Bind to second parameter by skipping the first one with "_"
var bound = _.bind(add, null, _, 4);
bound(3);
// → 7
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>

Ответ 3

Ну. Я просто выброшу это.

var add = function(a,b) {
  return a + b;
};

var addThree = function(a) {
  return add(a,3);
};

add(1,2);
addThree(4);

Возможно, это будет нормально для некоторых.

Ответ 4

вы можете попробовать следующее:

Function.prototype.bindThemAll = function bindThemAll(thisArg, ...boundArgs) 
  (boundArgs.fn = this, function(...args) boundArgs.fn.call(thisArg || this, ...boundArgs.map((el) => el || args.shift()), ...args));

function fn() console.log("fn:", arguments.callee, "this:", this, "args:", arguments)

var x = {a: 5};

var bfn = fn.bindThemAll(x, null, 2)
bfn(1,3)
x.bfn = fn.bindThemAll(null, null, 2)
x.bfn(1,3)