有没有更好(更干净)的方法来使用三元运算符(不重复代码)编写这个 JS 代码?

Posted

技术标签:

【中文标题】有没有更好(更干净)的方法来使用三元运算符(不重复代码)编写这个 JS 代码?【英文标题】:Is there a better(cleaner) way to write this JS code using ternary operators(without repeating code)? 【发布时间】:2019-08-17 11:36:34 【问题描述】:

所以我正在编写一个简单的 React.js 应用程序,只是有一个关于设置状态的问题,这可以做得更干净吗?

const enemy = this.state.enemy;
        if (this.state.isRock) 
            enemy === "rock"
                ? this.setState( result: "Draw!" )
                : enemy === "paper"
                ? this.setState( result: "You lose!" )
                : enemy === "scissors"
                ? this.setState( result: "You win!" )
                : this.setState( result: null );
         else if (this.state.isPaper) 
            enemy === "rock"
                ? this.setState( result: "You win!" )
                : enemy === "paper"
                ? this.setState( result: "Draw!" )
                : enemy === "scissors"
                ? this.setState( result: "You lose!" )
                : this.setState( result: null );
         else if (this.state.isScissors) 
            enemy === "rock"
                ? this.setState( result: "You lose!" )
                : enemy === "paper"
                ? this.setState( result: "You win!" )
                : enemy === "scissors"
                ? this.setState( result: "Draw!" )
                : this.setState( result: null );
        

【问题讨论】:

研究使用 switch 语句... 【参考方案1】:

考虑到只有三种可能的状态(赢、输、平),我们只需要检查其中的两种。平局很容易检查,所以我们只需要输赢的状态。这是一个例子:

const enemy = this.state.enemy;
let wins = 
    "rock"     : "scissors",
    "paper"    : "rock" ,
    "scissors" : "paper",

let play = (this.state.isRock ? "rock" : (
  this.state.isPaper ? "paper" : (
    this.state.isScissors ? "scissors" : null
    )
  )
)

if (!wins[play]) 
    this.setState( result: null )
 else if (enemy == play) 
    this.setState( result: "Draw!" )
 else if (wins[play] == enemy) 
    this.setState( result: "You win!" )
 else 
    this.setState( result: "You lose!" )

【讨论】:

是的,甚至可以通过将玩家的状态保存为字符串而不是这些 isXXX 布尔值来更简单:jsfiddle.net/5tfyqj6k【参考方案2】:

您可以将条件作为地图的一部分,因为条件永远不会改变并设置状态。

const condition = 
  "rock": 
    "paper": "You lose!",
    "sccissors": "You win!",
    "rock": "Draw!"
  ,
  "paper": 
    "rock": "You win!",
    "sccissors": "You lose!",
    "paper": "Draw!"
  ,
  "sccissors": 
    "rock": "You lose!",
    "paper": "You win!",
    "sccissors": "Draw!"
  
;

function getResult(enemy, isRock, isScissors, isPaper) 
  let result = null;
  
  if (isRock) 
    result = condition['rock'][enemy];
   else if (isPaper) 
    result = condition['paper'][enemy];
   else if (isScissors) 
    result = condition['scissors'][enemy];
  
  
  return result;


const 
  isRock, 
  isScissors,
  isPaper,
  enemy
 = this.state;


this.setState(
  result: getResult(enemy, isRock, isScissors, isPaper)
)

【讨论】:

【参考方案3】:

我有一个有趣的方法,您可以尝试使用 for in 循环和一个 if 语句。

您可以使用对象字面量来设置每个状态的值:

const stateConditions = 
    "isRock": 
      "paper": "You lose!",
      "scissors": "You win!",
      "rock": "Draw!"
    ,
    "isPaper": 
      "rock": "You win!",
      "scissors": "You lose!",
      "paper": "Draw!"
    ,
    "isScissors": 
      "rock": "You lose!",
      "paper": "You win!",
      "scissors": "Draw!"
    
  ;

在上面的对象中如果你做了 state = stateConditions['isRock'] 那么你会得到对应的 rock 条件

使用 javascript this.state['isRock'] 与 this.state.isRock 相同。并且您可以使用属性来循环使用forin 的对象中的每个属性,因此您可以执行以下操作来查找当前状态。这样你就可以遍历所有可能的状态,看看 this.state['somestate'] 是否为真:

for (let state in stateConditions) 
    if (this.state[state] === true) 
        // you found which state was true!
    

最终代码:

const conditions = 
    "isRock": 
      "paper": "You lose!",
      "scissors": "You win!",
      "rock": "Draw!"
    ,
    "isPaper": 
      "rock": "You win!",
      "scissors": "You lose!",
      "paper": "Draw!"
    ,
    "isScissors": 
      "rock": "You lose!",
      "paper": "You win!",
      "scissors": "Draw!"
    
  ;

  for (const state in conditions) 
      // check if this is the state
      if (this.state[state]) 
          this.setState( result: condition[state][this.state.enemy] );
          break;
      
  

这是replacing switch statements with object literals上的一篇有趣的文章

【讨论】:

【参考方案4】:

对当前答案之一进行不同的旋转,以减少重复:

const condition = 
  rock: 
    paper: -1,
    scissors: 1,
    rock: 0
  ,
  paper: 
    paper: 0,
    scissors: -1,
    rock: 1
  ,
  scissors: 
    paper: 1,
    scissors: 0,
    rock: -1
  
;

function getResult(enemy, isRock, isScissors, isPaper) 
  let result = null;

  if (isRock) 
    result = condition.rock[enemy];
   else if (isPaper) 
    result = condition.paper[enemy];
   else if (isScissors) 
    result = condition.scissors[enemy];
  

  return result === -1 ? "You loose!" : result === 1 ? "You win!" : result === 0 ? "Draw!" : null;


this.setState(
  result: getResult(this.state)
);

【讨论】:

以上是关于有没有更好(更干净)的方法来使用三元运算符(不重复代码)编写这个 JS 代码?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不重复自己的情况下编写三元运算符(又名 if)表达式

Delphi - 相当于 C# 的三元运算符? [复制]

有没有一种干净的方法来使用 symfony 2.6 设置 websocket

Python:拥有三元运算符的有效方法[重复]

在sql中使用exists来查找重复项,有没有更干净的方法?

有没有更好的方法来使用存储库在 Laravel 中分配 Eloquent 关系?