【问题标题】:Converting object literals into functions in ES6 Javascript在 ES6 Javascript 中将对象字面量转换为函数
【发布时间】:2019-10-28 17:11:47
【问题描述】:

我在hackernoon.com 上阅读this article,它试图解释一种将javascript Switch/Case 转换为自身功能版本的特定方法。

文章到了一个地步,他们设置了一个名为switchcase的函数,定义为:

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

他们还说这个函数有问题,因为“整个对象字面量在传递给 switchcase 函数之前都会被评估”。因此他们决定将对象文字中的值转换为函数。为此,他们使用以下语法:

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

我的问题是:最后一个语法是如何工作的?谁能帮我分解一下?

【问题讨论】:

  • 你是在说这行吗? switchcase(cases)(defaultCase)(key)()
  • @silencedogood 是的,我是。
  • switchcase(cases)(defaultCase)(key) - 返回cases[key] 或default,然后就叫它()
  • 在运行 switchcase(cases)(defaultCase)(key) 以返回 case[key] 然后调用它时,它不会只评估整个对象字面量吗?
  • 复制switchcase有什么好处?

标签: javascript ecmascript-6 functional-programming


【解决方案1】:

最后一个语法是如何工作的?谁能帮我分解一下?

考虑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 的原因是为了lazy evaluation。我们只在调用函数时评估() => 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

但是,请注意,您也可以使用 getter 使其与 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

希望能解开你的疑惑。

【讨论】:

    【解决方案2】:

    通过使用函数,您还需要为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'));

    【讨论】:

    • 实际上,你没有。预计defaultCase 是一个函数。 switchcase 的类型是 Map String a -> a -> String -> a,switchcaseF 的类型是 Map String (Thunk a) -> Thunk a -> String -> a。因此,在您的示例中,您将分别编写 switchcaseF({ foo: () => 'bar' })(() => 'nothing')('foo') 和 switchcaseF({ foo: () => 'bar' })(() => 'nothing')('baz')。
    【解决方案3】:

    如果用简单的函数重写它会被清除。

    首先,重写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();
    }
    

    【讨论】:

    • 需要返回selectedFunc的结果。
    • @AaditMShah,已修复
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 2018-12-04
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多