[SSD Series] оба указаны Cori, Anti-Cori, не узнают

внешний интерфейс JavaScript
[SSD Series] оба указаны Cori, Anti-Cori, не узнают

Это 4-й день моего участия в августовском испытании обновлений.Подробности о событии:Испытание августовского обновления.

предисловие

карриа такжечастичная функцияВсе они являются важными понятиями функционального программирования.Давайте сегодня взглянем на них с другой стороны.антикарринг.

Но так как он против каррирования, давайте сначала познакомимся с его сестрой.Каррирование и частичные функции.

Каррирование и частичные функции

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

Википедия говорит:

Каррирование, английский язык: Каррирование — это метод преобразования функции, которая принимает несколько параметров, в функцию, которая принимает один параметр (первый параметр исходной функции) и возвращает новую функцию, которая принимает остальные параметры и возвращает результат.

Эта техника была разработана логиком Кристофером Стрейчи.Haskell Curryназван, хотя он был изобретен Моисеем Шнфинкелем и Готтлобом Фреге.

Давайте рассмотрим пример, который более нагляден:

function sum(a, b, c) {
  return a + b + c;
}

function currySum(a){
    return function (b){
        return function (c){
            return a + b + c;
        }
    }
}
sum(1,2,3) // 6
currySum(1)(2)(3) // 6

Всего два момента:

  1. Многопараметрический проход

  2. Возвращаемая функция, если условие выполнено, должна выполнить функцию и вернуть результат

1.1.1 Трудности

Сложность общих функций каррирования заключается в том, как узнатьдлина аргументов функции, Обычно используемые методы:

  1. Function.prototype.lengthсвойство получить длину параметра

    Недостаток,остальные параметры не учитываются в длине.

    Следующий код, полученная длина которого равна 2, является лучшим фактом.

    function log(msg1, msg2, ...other){
        console.log(msg1, msg2, ...other);
    }
    
    console.log(log.length); // 2
    
  2. При каррировании отображалась длина входящего параметра

  3. Конечно, их можно комбинировать, и значение функции по умолчанию в порядке.

    function curry(fn, length = fn.length){
        // ....
    }
    

1.1.2 Заполнители


После каррики, концепция нескольких заполнителей, что это значит, то есть я не буду сначала пройти этот параметр, а затем передать его позже.

Взгляните на официальный пример lodash.

var abc = function(a, b, c) {
  return [a, b, c];
};
 
var curried = _.curry(abc);
// Curried with placeholders.
curried(1)(_, 3)(2);
// => [1, 2, 3]

Что касается реализации, расширенная версияlodash.curry, гражданская версияКаррирование функций в темах JavaScript.

1.2 Частичная функция

Подобно каррированию, просто понять, что параметры передаются дважды.

  1. Исправлены некоторые параметры впервые
  2. Второй проход по остальным параметрам

Посмотрите на официальный пример подчеркивания, в этом примере тоже есть заполнители, но это не влияет на понимание.

var subtract = function(a, b) { return b - a; };
sub5 = _.partial(subtract, 5);
sub5(20);
=> 15

// Using a placeholder
subFrom20 = _.partial(subtract, _, 20);
subFrom20(5);
=> 15

Что касается реализации, расширенная версияlodash.partialтак же какunderscore.partial, плохой вариантЧастичная функция javaScript тема

Здесь функция частичной функцииbindЕсть сходства.

Однако сегодня в центре внимания не они, а борьба с каррированием.

антикарринг

2.1 Концепция

Антикарринг – этоВсевозможность, брать чужие вещи и пользоваться ими.

Давайте рассмотрим пример: мы часто используем для определения типа данныхObject.prototype.toString

function unCurry(fn) {
    return function (context) {
        return fn.apply(context, Array.prototype.slice.call(arguments, 1));
    }
}

// 不使用反柯里化
Object.prototype.toString.call({});  // [object Object]

// 反柯里化
const toString = unCurry(Object.prototype.toString);
toString({});        // [object Object]
toString(() => { }); // [object Function]
toString(1);         // [object Number]

2.2 Реализация

2.2.1 Базовая версия: простая и понятная

function unCurry(fn) {
    return function (context) {
        return fn.apply(context, Array.prototype.slice.call(arguments, 1));
    }
}

2.2.2 Прототип: Вторжение + Удобство

Function.prototype.unCurry = function(){
    var self = this;
    return function(){
        return Function.prototype.call.apply(self, arguments);
    }
}

Эта версия взломает прототип, который мне не нравится. Удобство все еще там.
Две трудности в понимании

  1. self = this
    self равен самой функции, вот онавременная функция

  2. Function.prototype.call.apply(self, arguments)

Говоря о проблемах, обратите внимание на следующее преобразование.

Function.prototype.call.apply(self, arguments)
==>
Function.prototype.call.bind(self)(arguments)
==>
self.call(arguments)
==>
self.call(arguments[0], arguments[1-n]) // arguments[0]就是self函数的上下文了

Если вы используете его, он немного изменится

2.2.3 Прототип 2.

Я не буду это интерпретировать, каждый сам разберется

Function.prototype.unCurry = function () {
    return this.call.bind(this);
};

Возможен ли следующий код с ES6?

Function.prototype.unCurry = function () {
    return (...args) => this.call(...args)
};

Есть еще множество интересных способов письма, для более подробной информации см.# Carrying && Anti-Carrying

2.3 Сценарии использования

Антикаррирование — это идея, и ее реализацию определенно можно заменить другими решениями.Но еще один способ мышления означает еще один метод.

2.3.1 Оценка типа данных

Демонстрация выше была продемонстрирована.

2.3.2 Проталкивание массива (пример в расширенном программировании)

const push = unCurry(Array.prototype.push);
const arr = [1, 2, 3];
push(arr, 4, 5, 6);
console.log(arr);

2.3.3 Массив репликации

const clone = unCurry(Array.prototype.slice);

var a = [1,2,3];

var b = clone(a);

console.log("a==b", a === b);  // a==b false
console.log(a, b);  // [ 1, 2, 3 ] [ 1, 2, 3 ]

2.3.4 Отправка событий

    const dispatch = unCurry(EventTarget.prototype.dispatchEvent);

    window.addEventListener("event-x", (ev) => {
        console.log("event-x", ev.detail);  // event-x ok
    })

    dispatch(window, new CustomEvent("event-x", { detail: "ok" }));

Подробно объясните каррирование функций JS

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

Частичная функция темы JavaScript

Категории