Преобразование литералов объекта в функции в ES6 Javascript - PullRequest
1 голос
/ 28 октября 2019

Я читал эту статью на hackernoon.com, которая пытается объяснить особый подход к превращению переключателя JavaScript / Case в функциональную версию самого себя.

Статья достигает точкигде они устанавливают функцию с именем switchcase, определяемую как:

const switchcase = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key] : defaultCase

. Они также говорят, что у этой функции есть проблема, поскольку «весь литерал объекта оценивается перед передачей в функцию switchcase». И поэтому они решают преобразовать значения в литерале объекта в функции. Для этого они используют этот синтаксис:

const switchcaseF = cases => defaultCase => key =>
  switchcase(cases)(defaultCase)(key)()

Мой вопрос: как работает этот последний синтаксис? Кто-нибудь может сломать это для меня?

Ответы [ 3 ]

2 голосов
/ 28 октября 2019

Будет очищено, если переписать это с помощью простой функции.

Сначала переписать switchcase. Эта функция является результатом каррирования следующей функции с тремя аргументами

function switchcase(cases, defaultCase, key){
    if(cases.hasOwnProperty(key)){
        return cases[key];
    }
    return defaultCase;
}

Итак, если переписать switchcaseF, мы получим следующее:

function switchcaseF(cases, defaultCase, key){
    var selectedFunc = switchcase(cases, defaultCase, key);

    return selectedFunc();
}
2 голосов
/ 28 октября 2019

Используя функции, вам нужно взять функцию и для defaultCase.

const switchcase = cases => defaultCase => key =>
        cases.hasOwnProperty(key) ? cases[key] : defaultCase

const switchcaseF = cases => defaultCase => key =>
        switchcase(cases)(() => defaultCase)(key)()
//                        ^^^^^^^^^^^^^^^^^      ^^
  
console.log(switchcaseF({ foo: () => 'bar' })('nothing')('foo'));
console.log(switchcaseF({ foo: () => 'bar' })('nothing')('baz'));
0 голосов
/ 30 октября 2019

Как работает этот последний синтаксис? Может ли кто-нибудь разбить его для меня?

Рассмотрим определение switchcase и switchcaseF.

const switchcase = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key] : defaultCase

const switchcaseF = cases => defaultCase => key =>
  switchcase(cases)(defaultCase)(key)()

Если мы включим применение switchcase в switchaseF мы получаем следующее.

const switchcaseF = cases => defaultCase => key =>
  (cases.hasOwnProperty(key) ? cases[key] : defaultCase)()
//|____________________________________________________|
//                           |
//          switchcase(cases)(defaultCase)(key)

Кроме того, мы можем переместить приложение функции в условное выражение.

const switchcaseF = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key]() : defaultCase()

Теперь рассмотрим пример из article что вы связались с.

const counter = (state = 0, action) =>
  switchcaseF({
    'INCREMENT': () => state + 1,
    'DECREMENT': () => state - 1
  })(() => state)(action.type)

Если мы встроим приложение switchcaseF в counter, мы получим следующее.

const counter = (state = 0, action) => {
  const cases = {
    'INCREMENT': () => state + 1,
    'DECREMENT': () => state - 1
  }
  const defaultCase = () => state
  const key = action.type
  return cases.hasOwnProperty(key) ? cases[key]() : defaultCase()
}

Следовательно, если action.type равно 'INCREMENT' тогда результат state + 1. Если action.type равно 'DECREMENT', то результат равен state - 1. В противном случае результат будет state.

Причина, по которой мы пишем выражения типа () => state + 1 вместо простого state + 1, заключается в отложенной оценке . Мы оцениваем тело () => state + 1 только при вызове функции. Это предотвращает некорректное поведение, как в следующем примере.

const switchcase = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key] : defaultCase

const never = () => { while (true); }

const example = key => switchcase({
  never: never()
})('it works')(key)

console.log(example('it should work')) // expected 'it works' but never returns

Использование switchcaseF решает эту проблему.

const switchcaseF = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key]() : defaultCase()

const never = () => { while (true); }

const example = key => switchcaseF({
  never: () => never()
})(() => 'it works')(key)

console.log(example('it should work')) // 'it works' as expected

Однако учтите, что вы можете использовать геттеры, чтобы он работал и с switchcase.

const switchcase = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key] : defaultCase

const never = () => { while (true); }

const example = key => switchcase({
  get never() { return never(); }
})('it works')(key)

console.log(example('it should work')) // 'it works' as expected

Мы также можем сделать defaultCase ленивым.

const switchcase2 = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key] : defaultCase.value

const never = () => { while (true); }

const example = key => switchcase2({
  get never() { return never(); }
})({ get value() { console.log('yes'); return 'it works'; } })(key)

console.log(example('it should work')) // 'yes' 'it works' as expected

Если вы не хотите, чтобы он был ленивым, вы можете заключить его в strict следующим образом.

const switchcase2 = cases => defaultCase => key =>
  cases.hasOwnProperty(key) ? cases[key] : defaultCase.value

const never = () => { while (true); }

const strict = value => ({ value })

const example = key => switchcase2({
  get never() { return never(); }
})(strict('it works'))(key)

console.log(example('it should work')) // 'it works' as expected

Надеюсь, что прояснит ваши сомнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...