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

时间:2017-07-26 17:49:03

标签: javascript ecmascript-6 immutability

我坚持严格的函数式编程原则,没有变异。

如何以不会使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'

6 个答案:

答案 0 :(得分:11)

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

private void runCMDFile()
{
    string path = @"C:\Users\username\Desktop\yourFile.cmd";

    Process proc = new Process();                        

    proc.StartInfo.FileName = path;
    proc.StartInfo.UseShellExecute = true;
    proc.StartInfo.CreateNoWindow = false;
    proc.StartInfo.RedirectStandardOutput = false;
    proc.StartInfo.Verb = "runas";                         
    proc.Start();
    proc.WaitForExit();
}

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

你有两个担忧,并且将它们分开来帮助你

  1. 确定从小时开始的日期
  2. 组装问候语字符串
  3. 通过这样做,你可以避免

    1. 变异(const greeting = time > 12 ? (time > 17 ? 'Evening' : 'Afternoon') : 'Morning' 的本地重新分配)
    2. 单分支 if 语句
    3. 命令式风格的陈述(即greetingletifreturn
    4. 结果是使用表达式编写的两个纯(referentially transparent)函数 - 没有赋值(或重新赋值),并且没有副作用。

      
      
      x = ...
      
      
      

答案 1 :(得分:7)

WITH date1 AS (
  SELECT to_date('2017-07-26 02:37:00 AM','yyyy-MM-dd hh12:mi:ss am') dt2,
         to_date('2017-07-26 06:10:00 PM','yyyy-MM-dd hh12:mi:ss am') dt1 FROM DUAL
)
select TO_CHAR (greatest(dt2, trunc(dt2+(level-1)/24, 'hh24')),
    'dd-MON-yyyy HH12:MI:SS AM') FROM_DT,
    TO_CHAR (  least(dt1, trunc(dt2+(level)/24, 'hh24'),
    'dd-MON-yyyy HH12:MI:SS AM') TO_DT
    from date1 connect by level <= floor(
        (trunc(dt1,'HH')-trunc(dt2,'HH'))  *24) + case when (
             dt1 <> trunc(dt1,'HH')
        ) then 1 else 0 end

从技术上讲,这使您可以灵活地在将来添加更多时间,例如在第12小时添加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}!` 。此外,由于类似的原因,它使本地化更容易;某些区域设置可能有'Noon'个其他区域可能没有。

这原本是个笑话;)

答案 2 :(得分:2)

这个问题已经回答了,但如果你有3个以上的选择,你可以这样做:

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

答案 3 :(得分:2)

(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));
})();

答案 4 :(得分:1)

要清楚你没有做任何突变,你使用let而不是const。为什么它不是变异 - 因为字符串在javascript中是不可变的。所以你的问题更多 - &#34;如何将条件值分配给const&#34;。

要明确我在这里做这样的行为并没有发现任何问题。除非这不在函数范围之外,否则改变它就好了(我正在谈论更多关于一般方法,例如对象)。

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

到目前为止,我的答案是 - 保持原样,对我而言,它比具有许多条件的三元运算符更清晰。

答案 5 :(得分:0)

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

&#13;
&#13;
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)();
&#13;
&#13;
&#13;

请注意,虽然字符串值是不可变的,但String对象本身是可变的。您可以向该对象添加属性,您可以更改该属性的值;参见示例here

使用关键字const创建一个常量,并按MDN

  

常量的值不能通过重新赋值来改变   不能重新宣布。

在这个和其他例子中,根据一天三次表达的时间设定常数,常数本身是变量&#34;如果它的值根据脚本运行的时间而变化。