在 JavaScript 中的 Object 中使用短路 (||)

Posted

技术标签:

【中文标题】在 JavaScript 中的 Object 中使用短路 (||)【英文标题】:using Short-Circuiting ( || ) in Object in JavaScript 【发布时间】:2021-12-25 01:08:26 【问题描述】:

此代码块获取scored 属性的值并将它们作为键放入duplication 对象中,并使用|| 运算符将名称作为值重复多少次。 我知道|| 运算符将返回第一个真值或如果所有值都是假的,则返回最后一个值,但是,我不明白duplication[x]++ ++ 符号到底是做什么的?以及为什么我们将(duplication[x]=1) 放在括号之间

const game = 
  score: "4:0",
  scored: ["Lewandowski", "Gnarby", "Lewandowski", "Hummels"],
; 


const duplication = ;
for (let x of game.scored) 
 duplication[x]++ || (duplication[x]=1) // I'm confused in this line

 
console.log(duplication);

【问题讨论】:

|| 不是“短路”运算符。它是逻辑“或”运算符。它运行“a 或 b”,因此运行 duplication[x]++,如果这是错误的,则运行 (duplication[x]=1)。另外,记得写下你真正想知道的事情:如果你不知道++ 做什么,或者为什么有人会添加(),那么ask about that。但是,当然,只有在搜索 web/SO 以获得解释之后(对于 ++ 来说这是微不足道的,有成千上万的页面解释了它的作用)。 "所以它运行 duplication[x]++,如果这是错误的,它就会运行 (duplication[x]=1)" - 几乎就是短路评估的定义;如果评估运算符的另一端不会改变结果,则停止评估,即true || xfalse && x @Mike'Pomax'Kamermans 下次提问前会多搜索,感谢您对||的指正。 几乎字面意思不是字面意思:JS 并不称其为“短路运算符”,所以当我们谈论 JS 时,它不是这样的。它是logical or operator,您可以使用来短路条件。在提出技术问题时使用正确的术语并学习正确的术语总是很重要的。 @Mike'Pomax'Kamermans 我想我看到了这颗珍珠中心的沙粒。我同意 || 不是 the 短路运算符,我想你会同意 ||a 短路运算符(如果没有明确命名所以在 ECMA-262 中)。如果没有,那也没关系✌️ 【参考方案1】:

第一部分

duplication[x]++ || (duplication[x] = 1)
^^^^^^^^^^^^^^^^

有四个部分:

    一个变量duplication与 property accessorx 括号表示法 后缀increment operator ++ 和 logical OR || 运算符的表达式。

第二部分在第一次调用时返回undefined,带有未知属性。

尝试增加该值返回NaN,因为duplication[x] = duplication[x] + 1 的以下操作。结果是一个falsy 值。

这会强制表达式计算逻辑 OR 的右手部分。

因为左侧部分有一个表达式,所以需要先用grouping operator () 对其进行求值。现在赋值发生了,1 的结果返回给 OR。

【讨论】:

非常感谢您的详细解答!【参考方案2】:

非描述性的变量名称并不能真正帮助解释这种情况。让我们从用更具描述性的变量名称重写代码开始。

const game = 
  score: "4:0",
  scored: ["Lewandowski", "Gnarby", "Lewandowski", "Hummels"],
; 


const goals = ;
for (const player of game.scored) 
  goals[player]++ || (goals[player] = 1);

 
console.log(goals);

goals[player]++goalsplayer 加 1 并返回旧值。 goals[player]++ 中的棘手之处在于 player 可能还没有出现在 goals 中。在这种情况下,undefined 被返回(这是假的)。因为该值是假的,所以 OR 运算符的第二个操作数将被执行。 (goals[player] = 1) 会将 goalsplayer 设置为 1

代码本质上是计算特定名称在game.scored 数组中出现的频率。名字的出现象征着他们的目标。

编写类似代码的一种不那么神秘的方式是:

const goals = ;
for (const player of game.scored) 
  if (player in goals) 
    goals[player] += 1; // add 1 to the current score
   else 
    goals[player] = 1; // no score present so use 1
  

但是我通常更喜欢设置一个默认值,这样您就不必将逻辑拆分为两个操作:

const goals = ;
for (const player of game.scored) 
  goals[player] ||= 0; // assign 0 if the current value is falsy
  goals[player] += 1;  // add 1 to the current value

请注意,||= 是相当新的,如果您为旧版浏览器编写 javascript,您可以使用以下代码:

if (!goals[player]) goals[player] = 0;

【讨论】:

感谢您的详细解答!我还有 2 个问题: 1- 当我更改一些东西以了解代码时,我注意到将 duplication[x]++ 更改为 duplication[x]+=1 会返回 NaN 并且我不明白为什么这显然是一个数字... 2-当我从(duplication[x]=1) 中删除括号时,会出现此错误:分配中的左侧无效。为什么我不能分配 duplication[x]=1 而不把它放在括号内。 @MrXQ 1. 如果 value 尚未定义 (undefined),则 undefined + 1 //=> NaN。因为value++ 返回old 值,所以返回值将是undefined++valuevalue += 1value++ 执行相同的操作,但它们返回 new 值 (NaN) 而不是旧值。尽管所有三种情况都将value 设置为值NaN(这也是虚假的)。 (1/2) 2.不能删除括号的原因是|| 的precedence 比= 高。因此goals[player]++ || goals[player] = 1 将被评估为(goals[player]++ || goals[player]) = 1,这会导致错误,因为它是一个无效的 JavaScript 表达式。 (2/2)【参考方案3】:

让我们看看这一行发生了什么:

duplication[x]++ || (duplication[x]=1)

    duplication[x]++ ,首先duplication[x] 它将检查duplication 是否有任何值为x,如果是则它将执行duplication[x]++ 否则它将未定义移动到@ 的其他部分987654328@条件

    duplication[x]=1,这是一个简单的赋值,它将赋值为 1,duplication[x],如果在 duplication 对象中不存在,这将创建一个键

现在,如果您运行以下脚本并检查每个循环的控制台日志,它将让您清楚地知道实际发生了什么。

const game = 
  score: "4:0",
  scored: ["Lewandowski", "Gnarby", "Lewandowski", "Hummels"],
; 


const duplication = ;
let index = 0;

for (let x of game.scored) 

  console.log( `INDEX : $index ` , x , duplication[x] ? 'FOUND , INCREMENT CURRENT VALUE WITH ++' : 'NOT FOUND, SO ASSIGN VALUE 1' );
  duplication[x]++ || (duplication[x]=1)
  console.log( `INDEX : $index \n` , duplication);
  index++;


 
console.log( 'FINAL OBJECT \n' , duplication);

【讨论】:

"如果是,那么它将执行duplication[x]++ 否则它将是未定义的" - 非常接近,无论duplication[x] 中当前的值是什么,它都会后增量,但要针对其中的值进行测试duplication[x] 在增量之前。我实际上不确定这是否属于未定义的行为;在我看来,后增量可能发生在分配之后(duplication[x] = 1)。我个人会考虑duplication[x] = (duplication[x] || 0) + 1 是的,同意!但我只是想解释当前的代码,因为 OP 有点困惑,你的方法更好更清晰。 @msbit @VivekDoshi 非常感谢您的详细回答,现在我可以理解这一行的总体思路,但是我有两个问题 1- 当我更改一些内容以了解代码时,我注意到更改duplication[x]++duplication[x]+=1 返回NaN,我不明白为什么,这显然是一个数字... 2- 当我从(duplication[x]=1) 中删除括号时,它给出了这个错误: Invalid left-hand side in assignment 。为什么我不能分配 duplication[x]=1 而不把它放在括号内 @MrXQ,阅读这篇文章,***.com/a/43414179/2349407,这可能会帮助您解决问题

以上是关于在 JavaScript 中的 Object 中使用短路 (||)的主要内容,如果未能解决你的问题,请参考以下文章

如何在javascript中使作为数组元素的对象为空[重复]

如何在 Javascript 中使简单的 php 的 foreach 等效? [复制]

关于在 ASP.Net 中使 javascript 对象名称唯一的想法?

如何在 Python 中使私有变量可访问? [复制]

在 JavaScript 中的 Object 中使用短路 (||)

javascript中的Function和Object