在 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 || x
或false && 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]++
将 goals
的 player
加 1 并返回旧值。 goals[player]++
中的棘手之处在于 player
可能还没有出现在 goals
中。在这种情况下,undefined
被返回(这是假的)。因为该值是假的,所以 OR 运算符的第二个操作数将被执行。 (goals[player] = 1)
会将 goals
的 player
设置为 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
。 ++value
和 value += 1
与 value++
执行相同的操作,但它们返回 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 对象名称唯一的想法?