【问题标题】:Javascript Operators - Combining Nullish Coalescing with TernaryJavascript 运算符 - 将 Nullish Coalescing 与三元相结合
【发布时间】:2021-09-27 22:14:34
【问题描述】:

所以我有一些代码,我基本上试图在一行中执行 if、else if、else 语句,但基于无效性而不是真实性。

假设我在一个人对象上有一个布尔值“状态”:

let person = {
  status: true
}

我想根据以下条件显示文本:

  • 正确:“已验证”
  • 错误:“未验证”
  • 不存在:“正在加载...”

我可以像这样使用三元运算符:

person?.status ? 'Verified' : 'Not Verified'

但是如果person对象不存在,或者“status”字段不存在,它会返回一个假值。

如果我像这样使用 nullish 合并运算符:

person?.status ?? 'Loading...'

我可以通过非常简洁易读的代码获得所需的结果,但是如果不使用辅助函数,就无法格式化文本。

有没有办法将这些组合成一行可读的代码,或者我坚持编写一个辅助函数或使用更长的代码行:

person?.status == null ? 'Loading...' : (person.status ? 'Verified' : 'Not Verified')

也许我很挑剔,但我只是想知道是否有人有更优化、更简洁的方式来做到这一点。

感谢您的帮助!

【问题讨论】:

  • 如果 person 对象不存在,可选的链接不会拯救你,它会抛出一个错误。

标签: javascript optimization logic operators readability


【解决方案1】:

我只是想知道是否有人有更优化、更简洁的方式来做到这一点。

你有这个倒退。更简洁不是更具可读性。一行中的操作越多,就越难弄清楚它的作用:

a ?? b ? c ?? d?.e : f || x

如果不是全部在一行中,则更难从心理上解析。除其他事项外,您需要记住操作的顺序 - OR 是指 (f || x) 还是整个表达式到那里的 OR-ing?

它将被解析为(a ?? b ? c ?? d?.e : f) || x。然而,在你的脑海中评估这一点几乎没有帮助。

更优化和可读的方式是使用常规的if/else 语句

let status;
if (person?.status == null)
    status = 'Loading...';
else if (person.status)
    status = 'Verified';
else
    status = 'Not Verified';

如果需要,可以封装在一个函数中。

function status(person) {
    if (person?.status == null)
        return 'Loading...';
    if (person.status)
        return 'Verified';

    return 'Not Verified';
}

如果你真的需要一些简短的东西来使用,你可以有一个简单的查找表来解析不同的可能值:

const lookup = {
    "null" : 'Loading...',
    "true" : 'Verified',
    "false": 'Not Verified',
}

/* ... */

const status = lookup[person?.status ?? null];

也可以:删除 nullish 合并运算符并在查找中编码 undefined

const lookup = {
    "null"      : 'Loading...',
    "undefined" : 'Loading...',
    "true"      : 'Verified',
    "false"     : 'Not Verified',
}

/* ... */

const status = lookup[person?.status];

这几乎无关紧要,但有些有趣。您可以结合查找和函数来创建一个相当小的函数,该函数不使用if/elseswitch-es 来确定要返回的内容:

const status = person => ({
    "null"      : 'Loading...',
    "undefined" : 'Loading...',
    "true"      : 'Verified',
    "false"     : 'Not Verified',
})[person?.status];

console.log( status() );                //Loading...
console.log( status(null) );            //Loading...
console.log( status({}) );              //Loading...
console.log( status({status: true}) );  //Verified
console.log( status({status: false}) ); //Not Verified

这不是最佳做法,但偶尔会派上用场。它可以帮助制作原型。例如,从函数中提取对象是一个简单的重构,这反过来又允许您从配置中加载它。在这种情况下,如果您有类似的东西,它可能有助于将其翻译成不同的语言

{
  'english': {
        "null"      : 'Loading...',
        "undefined" : 'Loading...',
        "true"      : 'Verified',
        "false"     : 'Not Verified',
    },
  'pig-lating': {
        "null"      : 'Oadinglay...',
        "undefined" : 'Oadinglay...',
        "true"      : 'Erifiedvay',
        "false"     : 'Otnay Erifiedvay',
    }
}

【讨论】:

  • 基于函数的示例是唯一完全防止抛出错误的示例,因为它们保证 person 已被声明(在本例中作为参数)。否则,可选链接不足以防止这种情况发生。 person?. 要求至少已声明 person
  • @pilchard 一般来说,如果一个变量可能被声明或不被声明,那是一个大问题。我绝对不会建议使用可能未声明的东西。如果 person 未声明,调用 status(person) 仍然会抛出错误,因为它仍然会读取并且变量仍然不存在。
  • 我同意,但是 OP 特别提到 '但是如果 person 对象不存在,' 这似乎表明他们对可选链接的误解。否则,完全同意你的回答!
  • @pilchard OP 对该属性使用相同的术语。而且似乎OP的当前实现不会引发错误。因此,我假设 OP 的意思是“存在”,就像“它不是空的或未定义的”一样。或者换句话说“变量已被分配”。
猜你喜欢
  • 1970-01-01
  • 2020-09-10
  • 2020-12-19
  • 2016-06-26
  • 2015-09-21
  • 1970-01-01
  • 2020-03-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多