如何在没有突变的情况下分配条件变量?

How do I assign a conditional variable without mutation?

我坚持严格的函数式编程原则,不改变。

我如何以不改变 greeting 变量并且不在每个 if 块中返回它的方式编写类似下面的代码?

const greet = (name, time) => { 
  let greeting = 'Morning';

  if(time >= 12) {
    greeting = 'Afternoon';
  }
  if(time >= 17) {
    greeting = 'Evening';
  }

  return `Good ${greeting} ${name}!`;
};

如果只有两个条件我会做下面的,但是有3个条件就不行了:

const greeting = time > 12 ? 'Afternoon' : 'Morning'

Ternary expressions 可以组成其他三元表达式——允许我们对逻辑选择进行排序

const greeting = time > 12 ? (time > 17 ? 'Evening' : 'Afternoon') : 'Morning'

但是,我认为是 变量 使 变量 成为 变量.. .


虽然您有两个问题,但将它们分开对您有益

  1. 根据小时确定天数
  2. 组装问候语字符串

通过这样做,您可以避免

  1. 突变(greeting 的局部重新分配)
  2. 单分支if 语句
  3. 命令式语句(即 letifreturnx = ...

结果是两个使用 表达式编写的纯 (referentially transparent) 函数 – 没有赋值(或重新赋值),也没有副作用。

const timeToPeriod = time =>
  time >= 17
    ? 'Evening'
    : time >= 12
      ? 'Afternoon'
      : 'Morning'

const greet = (name, time) =>
  `Good ${timeToPeriod(time)} ${name} !`
  
console.log(greet('Jonas', 9))  // Good Morning Jonas !
console.log(greet('Jonas', 13)) // Good Afternoon Jonas !
console.log(greet('Jonas', 22)) // Good Evening Jonas !

const greeting = [
  'Morning', 'Morning', 'Morning', 'Morning', 'Morning', 'Morning', 'Morning', 
  'Morning', 'Morning', 'Morning', 'Morning', 'Morning',
  'Afternoon', 'Afternoon', 'Afternoon', 'Afternoon', 'Afternoon',
  'Evening', 'Evening', 'Evening', 'Evening', 'Evening', 'Evening', 'Evening'
]

return `Good ${greeting[time]} ${name}!`

从技术上讲,这使您可以灵活地在未来添加更多时间,例如在第 12 个小时添加 'Noon'。此外,出于类似的原因,它使本地化变得更容易;某些语言环境可能有 Noon 其他语言环境可能没有。

这本来是个玩笑 ;)

这个问题已经回答了,但是,如果你有超过 3 个选项,你可以这样做:

['Evening', 'Afternoon', 'Morning']
[
[17,12,0].findIndex((el) => time >= el)
]

在 JavaScript 中,变量本质上是不可变的。但是,您可以拥有不可变的表达式,方法是使用字符串值或声明常量。该解决方案依赖于三个常量。一个常量是一个对象,其中包含与 24 小时时间跨度中的三个时间段对应的字符串值。第二个常量保存一天中时间 (tod) 的测试结果。并且,最后一个常量保存了一个函数表达式,即匿名函数,如下:

let d = new Date();
let time = d.getHours();

const greeting = {
  "morn": "morning",
  "after": "afternoon",
  "evg": "evening"
};

const greet = function(strName) {
  const tod = (time < 12) ? greeting["morn"] :
    (time > 17) ? greeting["evg"] : greeting["after"];

  let salutation = "Good " + tod;
  salutation += ",";
  strName += "!";

  // adding another functional programming touch
  return function() {
    console.log([salutation, strName].join(" "));
  };
};

var user = "Zander";
greet(user)();

请注意,字符串值是不可变的,而字符串对象本身是可变的。您可以向该对象添加一个 属性,并且您可以更改该 属性 的值;参见示例 here.

使用关键字 const 创建常量并根据 MDN:

The value of a constant cannot change through re-assignment, and it can't be redeclared.

在这个和其他例子中,常数是根据一天中的时间相对于三元表达式设置的,常数本身是 "variable",其值根据时间的不同而变化脚本运行的日期。

(function (){
    const greet = (name, time) => { 
        const greetings = [ // Order is important
            {greeting: 'Evening',time: 17},
            {greeting: 'Afternoon',time: 12},            
            {greeting: 'Morning',time: -Infinity}
        ];
        const greeting = greetings.find(e=>time>=e.time).greeting;
        return `Good ${greeting} ${name}!`;
    }
    console.log(greet('Me',17));
})();

需要说明的是,您没有进行任何修改,您使用的是 let 而不是 const。为什么它不是突变 - 因为字符串在 javascript 中是不可变的。所以你的问题更多 - "How assign conditional value to const".

需要说明的是,我认为在此处执行 let 以及此类行为没有任何问题。在这不超出函数范围之前,改变它就可以了(我更多地谈论一般方法,例如对象)。

不变性规则应用于在函数范围之外声明的结构。什么直接意味着你永远不应该改变功能输入,永远不要触摸不属于你的东西。

对于这一点,我的回答是 - 保持原样,对我来说它比具有许多条件的三元运算符更清晰。