JavaScript OR(||)变量赋值说明

给出这段JavaScript代码…

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';


var f = a || b || c || d || e;


alert(f); // 4

有人能给我解释一下这个技巧叫什么吗(我最好的猜测是在这个问题的标题中!)?它究竟是如何/为什么工作的?

我的理解是变量f将被分配到第一个变量的最接近的值(从左到右),该变量的值既不是null也不是undefined,但我没有设法找到关于这种技术的很多参考资料,并且已经看到它被大量使用。

另外,这种技术是JavaScript特有的吗?我知道在PHP中做类似的事情会导致f有一个真正的布尔值,而不是d本身的值。

397215 次浏览

有关解释请参见短路的评估。这是实现这些运算符的常用方式;它并不是JavaScript独有的。

Javascript变量没有类型,所以f可以被赋值为整数值,即使它是通过布尔运算符赋值的。

f被赋给最接近的值不等于false。0, false, null, undefined,都被传递:

alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'

它没有任何魔力。像a || b || c || d这样的布尔表达式是延迟求值的。Interpeter寻找a的值,它是未定义的,所以它是假的,所以它继续前进,然后它看到b是空的,它仍然给出假的结果,所以它继续前进,然后它看到c -同样的故事。最后,它看到d并说“嗯,它不是空的,所以我有我的结果”,然后它将它赋值给final变量。

这个技巧适用于所有对布尔表达式进行惰性短路计算的动态语言。在静态语言中它不会被编译(类型错误)。在渴望计算布尔表达式的语言中,它将返回逻辑值(即在本例中为true)。

这意味着如果设置了x,则z的值将为x,否则,如果设置了y,则其值将设置为z的值。

这和

if(x)
z = x;
else
z = y;

这是可能的,因为JavaScript中的逻辑运算符并不返回布尔值,而是返回完成操作所需的最后一个元素的值(在OR句中,它将是第一个非假值,在AND句中,它将是最后一个)。如果操作失败,则返回false

如果x变量为falsy,则为默认值赋值,在本例中为y

JavaScript中的布尔运算符可以返回一个操作数,而不总是像其他语言中那样返回布尔结果。

逻辑或操作符(||)返回其第二个操作数的值,如果第一个操作数是假的,否则返回第一个操作数的值。

例如:

"foo" || "bar"; // returns "foo"
false || "bar"; // returns "bar"

Falsy值是那些在布尔上下文中使用时强制为false的值,它们是0nullundefined,一个空字符串,NaN,当然还有false

它将计算X,如果X不为空字符串或0(逻辑错误),那么它将把它赋值给z。如果X为空字符串或0(逻辑错误),那么它将把y赋值给z。

var x = '';
var y = 'bob';
var z = x || y;
alert(z);

将输出'bob';

它将新变量(z)设置为x的值,如果它是“真值”(非零,有效对象/数组/函数/无论它是什么),否则设置为y。这是在x不存在的情况下提供默认值的一种相对常见的方式。

例如,如果你有一个接受可选回调参数的函数,你可以提供一个默认的不做任何事情的回调:

function doSomething(data, callback) {
callback = callback || function() {};
// do stuff with data
callback(); // callback will always exist
}

Javacript使用短路的评估作为逻辑运算符||&&然而,它与其他语言的不同之处在于,它返回停止执行的最后一个值的结果,而不是__ABC2或false值。

以下值在JavaScript中被认为是假的。

  • ""(空字符串)
  • 0
  • 未定义的

忽略运算符优先级规则,并保持简单,下面的例子显示了哪个值停止了求值,并作为结果返回。

false || null || "" || 0 || NaN || "Hello" || undefined // "Hello"

NaN之前的前5个值都是假的,所以它们都从左到右求值,直到它遇到第一个真值——"Hello",它使整个表达式为真,所以再往上的任何值都不会求值,并且"Hello"作为表达式的结果返回。类似地,在这种情况下:

1 && [] && {} && true && "World" && null && 2010 // null

前5个值都是真值,直到它遇到第一个使表达式为假的假值(null),所以2010不再被求值,并且null作为表达式的结果返回。

您给出的示例是使用JavaScript的这个属性来执行赋值。它可以用于需要在一组值中获得第一个真值或假值的任何地方。下面的代码将值"Hello"赋值给b,因为这样更容易赋值默认值,而不是进行if-else检查。

var a = false;
var b = a || "Hello";

您可以将下面的示例称为对该特性的利用,我相信它会使代码更难阅读。

var messages = 0;
var newMessagesText = "You have " + messages + " messages.";
var noNewMessagesText = "Sorry, you have no new messages.";
alert((messages && newMessagesText) || noNewMessagesText);

在警报中,我们检查messages是否为假值,如果是,则计算并返回noNewMessagesText,否则计算并返回newMessagesText。由于在本例中它是假的,我们在noNewMessagesText处停下来并警告"Sorry, you have no new messages."

根据比尔·希金斯的博客帖子;Javascript逻辑或赋值习惯用法(2007年2月),此行为在v1.2(至少)是正确的

他还提出了它的另一种用法(引用): “跨浏览器差异的轻量级规范化”< / p >
// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;

返回输出第一个真值

如果全部为假,则返回最后一个假值。

例子:-

  null || undefined || false || 0 || 'apple'  // Return apple

这个问题已经得到了几个很好的答案。

总之,这种技术利用了语言编译方式的一个特性。也就是说,JavaScript“短路”;布尔运算符的求值,将返回与第一个非假变量值或最后一个变量包含的任何值相关联的值。参见Anurag对这些值的解释,这些值将被计算为假。

出于几个原因,使用这种技术并不是一种好的实践;然而。

  1. 代码可读性:这是使用布尔运算符,如果不理解如何编译的行为,那么预期的结果将是一个布尔值。

  2. 稳定性:这是使用语言如何在多种语言之间不一致的编译特性,因此它可能是未来可能改变的目标。

  3. 文档化特性:现有的替代方案满足了这一需求,并且在更多语言中是一致的。这将是三元操作符:

    () ?取值1:取值2。

使用三元操作符确实需要更多的输入,但它可以清楚地区分要计算的布尔表达式和要赋值的值。此外,它还可以被链接,因此可以重新创建上面执行的默认赋值类型。

var a;
var b = null;
var c = undefined;
var d = 4;
var e = 'five';


var f =  ( a ) ? a :
( b ) ? b :
( c ) ? c :
( d ) ? d :
e;


alert(f); // 4

它叫做短路操作员。

短路求值表示,只有当第一个参数不足以确定表达式的值时,才执行或求值第二个参数。当OR(||)函数的第一个参数为true时,整体值必须为true。

它也可以用来设置函数参数的默认值。

function theSameOldFoo(name){
name = name || 'Bar' ;
console.log("My best friend's name is " + name);
}
theSameOldFoo();  // My best friend's name is Bar
theSameOldFoo('Bhaskar');  // My best friend's name is Bhaskar`