83

我知道在 JavaScript 中你可以这样做:

var oneOrTheOther = someOtherVar || "these are not the droids you are looking for...";

oneOrTheOther如果变量不是 、 或 ,则变量将采用第一个null表达式undefined的值false。在这种情况下,它被分配给第二条语句的值。

但是,oneOrTheOther当我们使用逻辑 AND 运算符时,变量会分配给什么?

var oneOrTheOther = someOtherVar && "some string";

someOtherVar非假时会发生什么?假的
时候会发生什么?someOtherVar

刚刚学习 JavaScript,我很好奇与 AND 运算符一起赋值会发生什么。

4

7 回答 7

110

基本上,逻辑与运算符 ( &&) 如果第一个操作数为真,则返回第二个操作数的值,如果它本身为,它将返回第一个操作数的值例如:

true && "foo"; // "foo"
NaN && "anything"; // NaN
0 && "anything";   // 0

请注意,虚假值是在布尔上下文中使用时强制转换为false的值,它们是null, undefined, 0, NaN, 一个空字符串,当然false,其他任何东西都会强制转换为true.

于 2010-07-02T05:28:29.453 回答
38

&&有时被称为守卫操作员。

variable = indicator && value

仅当指标为真时才可用于设置值。

于 2010-07-02T05:37:07.853 回答
25

初学者示例

如果您尝试访问“user.name”,但会发生这种情况:

Uncaught TypeError: Cannot read property 'name' of undefined 

不要害怕。您现在可以在现代浏览器上使用 ES6 可选链。

const username = user?.name;

参见 MDN:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining

这里有一些关于守卫运算符的更深入的解释,可能有助于理解。

在引入可选链接之前,您可以在赋值中使用&& 运算符来解决这个问题,或者通常称为保护运算符,因为它可以“保护”未定义的错误发生。

这里有一些你可能会觉得奇怪的例子,但请继续阅读,稍后会解释。

var user = undefined;
var username = user && user.username;
// no error, "username" assigned value of "user" which is undefined

user = { username: 'Johnny' };
username = user && user.username;
// no error, "username" assigned 'Johnny'

user = { };
username = user && user.username;
// no error, "username" assigned value of "username" which is undefined

解释:在守卫操作中,每次从左到右评估每个术语。如果评估的值是虚假的,则评估停止,然后分配该值。如果达到最后一项,则分配它是否为假。

falsy意味着它是这些值中的任何一个,undefined, false, 0, null, NaN, ''truthy只是意味着不虚假。

奖励:OR 运算符

实际使用中的另一个有用的奇怪赋值是OR 运算符,它通常用于如下插件:

this.myWidget = this.myWidget || (function() {
   // define widget
})();

如果“this.myWidget”是假的,它只会分配代码部分。这很方便,因为您可以在任何地方多次声明代码,而不用关心它之前是否已分配,知道它只会被分配一次,因为使用插件的人可能会不小心多次声明您的脚本标签 src。

解释: 每个值都是从左到右计算的,一次一个。如果一个值是真值,它会停止评估并分配该值,否则,继续进行,如果到达最后一项,则无论它是否为假,它都会被分配。

额外学分:结合 && 和 || 在作业中

你现在拥有了终极力量,可以做一些非常奇怪的事情,比如在回文中使用它的这个非常奇怪的例子。

function palindrome(s,i) {
 return (i=i || 0) < 0 || i >= s.length >> 1 || s[i] == s[s.length - 1 - i] && isPalindrome(s,++i);
}

在这里深入解释:Javascript中的回文检查

快乐编码。

于 2014-08-11T15:01:07.540 回答
19

引用道格拉斯·克罗克福德1

如果第&&一个操作数是假的,则运算符产生其第一个操作数的值。否则它产生第二个操作数的值。


1 Douglas Crockford:JavaScript:好的部分——第 16 页

于 2010-07-02T05:28:13.137 回答
2

根据带注释的 ECMAScript 5.1 第 11.11 节

在逻辑 OR 运算符 (||) 的情况下,

expr1 || expr2 如果可以转换为 true,则返回 expr1;否则,返回 expr2。因此,当与布尔值一起使用时,|| 如果任一操作数为真,则返回真;如果两者都为假,则返回假。

在给定的示例中,

var oneOrTheOther = someOtherVar || “这些不是你要找的机器人……继续前进”;

如果 Boolean(someOtherVar) 为真,则结果将是 someOtherVar 的值。(请参阅。表达式的真实性)。如果它是假的,结果将是“这些不是你正在寻找的机器人......继续前进”;

如果是逻辑与运算符(&&),

如果可以转换为 false,则返回 expr1;否则,返回 expr2。因此,当与布尔值一起使用时,如果两个操作数都为真,则 && 返回真;否则,返回 false。

在给定的示例中,

情况 1:当 Boolean(someOtherVar) 为 false 时:返回 someOtherVar 的值。

案例 2:当 Boolean(someOtherVar) 为真时:它返回“这些不是您正在寻找的机器人......继续前进”。

于 2014-08-11T16:17:06.997 回答
1

我对此的看法与大多数答案不同,所以我希望这对某人有所帮助。

要计算一个涉及 的表达式||,您可以在找到一个为真的术语后立即停止计算该表达式。在这种情况下,你有两个知识,而不仅仅是一个:

  1. 给定术语为真,整个表达式的计算结果为真。
  2. Knowing 1, you can terminate the evaluation and return the last evaluated term.

For instance, false || 5 || "hello" evaluates up until and including 5, which is truthy, so this expression evaluates to true and returns 5.

So the expression's value is what's used for an if-statement, but the last evaluated term is what is returned when assigning a variable.

Similarly, evaluating an expression with && involves terminating at the first term which is falsy. It then yields a value of false and it returns the last term which was evaluated. (Edit: actually, it returns the last evaluated term which wasn't falsy. If there are none of those, it returns the first.)

If you now read all examples in the above answers, everything makes perfect sense :)

(This is just my view on the matter, and my guess as to how this actually works. But it's unverified.)

于 2021-07-12T09:27:52.597 回答
0

我在工作中看到 && 在这里过度使用赋值语句。关注点是双重的:1)“指标”检查有时是一个开发人员不考虑开销的函数。2)开发人员很容易将其视为安全检查,而不是认为他们将 false 分配给他们的 var。我喜欢他们有类型安全的态度,所以我让他们改变这个:

var currentIndex = App.instance && App.instance.rightSideView.getFocusItemIndex();

对此:

var currentIndex = App.instance && App.instance.rightSideView.getFocusItemIndex() || 0;

所以他们按预期得到一个整数。

于 2017-04-03T21:33:09.087 回答