Связывание и каррирование в JavaScript

Mar 4, 2018

Связывание (bind)

Связывание - создание ф-и, которая вызывает другую ф-ю со специфическим значением this и специфическими аргументами.

// Собственная ф-я bind
function bind(fn, context) {
    return function(){
        return fn.apply(context, arguments)
    }
};

// Пример использования

var ex1 = {
    text: 'Hello',
    callb: function(a) {
        return `${this.text} ${a}!`;
    }
};
var ex1_1 = {
    text: 'Привет'
};

var testFu1 = bind(ex1.callb, ex1_1);

console.log(testFu1('Johny'));// Привет Johny!

В ES5 реализован системный метод bind(), который работает аналогичным образом.

var testFu2 = ex1.callb.bind(ex1_1);

console.log(testFu2('Johny2')); // Привет Johny2!

Каррирование

Каррирование (curry, частичное применение ф-й) - при каррировании создается ф-я c одним или несколькими уже заданными аргументами. Основы методики аналогичны связыванию: возвращение новой функции + замыкание. Отличие каррирование в том, что новой ф-и задаются дополнительные аргументы.

// Универсальный способ создания каррированных ф-й:
function curry(fn) {
    // fn - ф-я, котор необходимо каррировать

    // slice() возвращает новый массив, отсчет с 2-го эл-та массива
    var args = Array.prototype.slice.call(arguments, 1);
    // args - содержит аргументы внешней ф-и, кроме первого


    return function() {
        var innerArgs = Array.prototype.slice.call(arguments),
        // innerArgs - хранит аргументы внутренней ф-и
            finalArgs = args.concat(innerArgs);
        return fn.apply(null, finalArgs);
        // null означает, что контест не учитываем

    }
};

function add(a, b) {
    return a + b;
};
var curried = curry(add, 23);
console.log(curried(12)); // 35

// или сразу все арг-ты во внешнею
console.log(curry(add, 23, 23)()); // 46

// Каррирование и связывание
// Создадим более сложную ф-ю bind

function bindCurry(fn, context) {
    // отсчет с 3-го эл-та массива
    var args = Array.prototype.slice.call(arguments, 2);
    return function() {
        var innerArgs = Array.prototype.slice.call(arguments),
        // innerArgs - хранит аргументы внутренней ф-и
            finalArgs = args.concat(innerArgs);
        return fn.apply(context, finalArgs);
    }
}

// пример:
var ex_curry = {
    text: 'Hello',
    callb: function(family, name) {
        return `${this.text} ${name} ${family}!`;
    }
};
var ex_curry1 = {
    text: 'Привет'
};

var testFuCurry = bindCurry(ex_curry.callb, ex_curry1, 'Dow');
console.log(testFuCurry('Johny'));

В методе bind() (ES5) также реализовано каррирование, после this можно передать дополнительный аргумент.

Добавить комментарий