407

Given this snippet of 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

Can someone please explain to me what this technique is called (my best guess is in the title of this question!)? And how/why it works exactly?

My understanding is that variable f will be assigned the nearest value (from left to right) of the first variable that has a value that isn't either null or undefined, but I've not managed to find much reference material about this technique and have seen it used a lot.

Also, is this technique specific to JavaScript? I know doing something similar in PHP would result in f having a true boolean value, rather than the value of d itself.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
chattsm
  • 4,651
  • 5
  • 19
  • 20
  • 4
    Old question, but regarding PHP, there is a construct you can use: `$f=$a or $f=$b or $f=$c; // etc`. PHP has both the `||` operator and the `or` operator, which do the same job; however `or` is evaluated _after_ assignment while `||` is evaluated before. This also give you the perlish style of `$a=getSomething() or die('oops');` – Manngo Oct 14 '16 at 07:30
  • 1
    In PHP 5.3 you can leave out the middle part of the ternary operator so basing from that... You can also cut that a bit shorter into something like this: `$f = $a ?: $b ?: $c;` – Rei Nov 30 '17 at 10:31
  • 1
    As of PHP 7 you can use `??` for this. `$a = $b ?? 'default'` – Spencer Ruskin Mar 19 '18 at 23:09
  • @SpencerRuskin so `$a` will be assigned the value of `$b` if `$b` is true, other `'default'`? – oldboy Mar 22 '19 at 18:31
  • That's right. Look at the null coalescing operator section on this page: https://www.php.net/manual/en/migration70.new-features.php – Spencer Ruskin Mar 29 '19 at 14:54

12 Answers12

249

See short-circuit evaluation for the explanation. It's a common way of implementing these operators; it is not unique to JavaScript.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
unwind
  • 391,730
  • 64
  • 469
  • 606
  • 61
    Just mind the 'gotcha' which is that the last one will always get assigned even if they're all undefined, null or false. Setting something you know isn't false, null, or undefined at the end of the chain is a good way to signal nothing was found. – Erik Reppen Aug 29 '11 at 16:51
  • 1
    I've seen this technique for years, but what striked me just then when I wanted to use it is that the result of the expression is not cast to boolean. You cannot later do `if( true == f )`. If an integer was stored in f, then this test will always return false. –  Aug 01 '13 at 02:11
  • 10
    Actually, you can do `if(true == f)`, which is the same as `if(f)`: the test will pass. If you want to also test the *type* of `f`, use strict comparison: `if(true === f)`, which will fail indeed. – Alsciende Jun 06 '16 at 09:44
  • 5
    Yes, short-circuit evaluation is common. But the distinction here lies in the way JavaScript returns the last value that halted the execution. @Anurag's answer does a much better job of explaining this. – Ben.12 Dec 01 '17 at 21:58
  • not sure if that is the best explanation for beginners. I would recommend: https://javascript.info/logical-operators – csguy Jun 07 '20 at 20:43
241

This is made to assign a default value, in this case the value of y, if the x variable is falsy.

The boolean operators in JavaScript can return an operand, and not always a boolean result as in other languages.

The Logical OR operator (||) returns the value of its second operand, if the first one is falsy, otherwise the value of the first operand is returned.

For example:

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

Falsy values are those who coerce to false when used in boolean context, and they are 0, null, undefined, an empty string, NaN and of course false.

Christian C. Salvadó
  • 807,428
  • 183
  • 922
  • 838
239

Javacript uses short-circuit evaluation for logical operators || and &&. However, it's different to other languages in that it returns the result of the last value that halted the execution, instead of a true, or false value.

The following values are considered falsy in JavaScript.

  • false
  • null
  • "" (empty string)
  • 0
  • Nan
  • undefined

Ignoring the operator precedence rules, and keeping things simple, the following examples show which value halted the evaluation, and gets returned as a result.

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

The first 5 values upto NaN are falsy so they are all evaluated from left to right, until it meets the first truthy value - "Hello" which makes the entire expression true, so anything further up will not be evaluated, and "Hello" gets returned as a result of the expression. Similarly, in this case:

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

The first 5 values are all truthy and get evaluated until it meets the first falsy value (null) which makes the expression false, so 2010 isn't evaluated anymore, and null gets returned as a result of the expression.

The example you've given is making use of this property of JavaScript to perform an assignment. It can be used anywhere where you need to get the first truthy or falsy value among a set of values. This code below will assign the value "Hello" to b as it makes it easier to assign a default value, instead of doing if-else checks.

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

You could call the below example an exploitation of this feature, and I believe it makes code harder to read.

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

Inside the alert, we check if messages is falsy, and if yes, then evaluate and return noNewMessagesText, otherwise evaluate and return newMessagesText. Since it's falsy in this example, we halt at noNewMessagesText and alert "Sorry, you have no new messages.".

Marjan Venema
  • 19,136
  • 6
  • 65
  • 79
Anurag
  • 140,337
  • 36
  • 221
  • 257
  • 48
    This is the best answer in my opinion because of the following explanation: `However, it's different to other languages in that it returns the result of the last value that halted the execution, instead of a true, or false value.` – mastazi Dec 28 '15 at 03:48
  • 1
    @mastazi Yep, it should go in bold font IMHO. – noober Jan 24 '16 at 23:51
  • 6
    Should be the answer, it shows the values being chosen over test cases. – Aesthetic Sep 14 '16 at 10:15
  • Agreed, this is my favorite answer as it specifically addresses JavaScript variable assignment concerns. Additionally, if you choose to use a ternary as one of the subsequent variables to test for assignment (after the operator) you must wrap the ternary in parentheses for assignment evaluation to work properly. – Joey T Jan 29 '19 at 21:19
54

Javascript variables are not typed, so f can be assigned an integer value even though it's been assigned through boolean operators.

f is assigned the nearest value that is not equivalent to false. So 0, false, null, undefined, are all passed over:

alert(null || undefined || false || '' || 0 || 4 || 'bar'); // alerts '4'
Alsciende
  • 26,583
  • 9
  • 51
  • 67
  • 13
    Don't forget `''` also equal false in this case. – Brigand Apr 04 '13 at 17:07
  • Upvote for pointing out that `f is assigned the NEAREST value` which is a pretty important point here. – steviesh Jun 06 '16 at 03:45
  • 3
    "Nearest" isn't quite true, though it does have that appearance. The boolean `||` operator, being a boolean operator has two operands: a left side and a right side. If the left side of the `||` is *truthy*, the operation resolves to the left side and the right side is ignored. If the left side is *falsy*, it resolves to the right side. So `null || undefined || 4 || 0` actually resolves to `undefined || 4 || 0` which resolves to `4 || 0` which resolves to `4`. – devios1 Oct 16 '17 at 16:26
  • @devios1 but `4` is nearest – milos Oct 19 '21 at 09:13
32

There isn't any magic to it. Boolean expressions like a || b || c || d are lazily evaluated. Interpeter looks for the value of a, it's undefined so it's false so it moves on, then it sees b which is null, which still gives false result so it moves on, then it sees c - same story. Finally it sees d and says 'huh, it's not null, so I have my result' and it assigns it to the final variable.

This trick will work in all dynamic languages that do lazy short-circuit evaluation of boolean expressions. In static languages it won't compile (type error). In languages that are eager in evaluating boolean expressions, it'll return logical value (i.e. true in this case).

Marcin
  • 7,874
  • 7
  • 45
  • 49
  • 6
    In the pretty static language C# one can use the ?? operator á la: object f = a ?? b ?? c ?? d ?? e; – herzmeister Jan 20 '10 at 11:14
  • 2
    herzmeister - thanks! I didn't know that ?? operator can be chained in C# and used in lazy evaluation techniques – Marek Mar 08 '12 at 08:49
  • 3
    As mentioned elsewhere, that last `d` will be assigned whether or not it was null/undefined or not. – BlackVegetable Jul 02 '13 at 17:17
  • One slight correction: the `||` operator always resolves to the whole right side operand when the left side is falsy. Being a boolean operator it only sees two inputs: the left side and the right side. The parser doesn't see them as a series of terms, so it doesn't actually stop when it finds the first truthy value *unless* that value is also the left hand operand of another `||`. – devios1 Oct 16 '17 at 16:38
10

This question has already received several good answers.

In summary, this technique is taking advantage of a feature of how the language is compiled. That is, JavaScript "short-circuits" the evaluation of Boolean operators and will return the value associated with either the first non-false variable value or whatever the last variable contains. See Anurag's explanation of those values that will evaluate to false.

Using this technique is not good practice for several reasons; however.

  1. Code Readability: This is using Boolean operators, and if the behavior of how this compiles is not understood, then the expected result would be a Boolean value.

  2. Stability: This is using a feature of how the language is compiled that is inconsistent across multiple languages, and due to this it is something that could potentially be targeted for change in the future.

  3. Documented Features: There is an existing alternative that meets this need and is consistent across more languages. This would be the ternary operator:

    () ? value 1: Value 2.

Using the ternary operator does require a little more typing, but it clearly distinguishes between the Boolean expression being evaluated and the value being assigned. In addition it can be chained, so the types of default assignments being performed above could be recreated.

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
Community
  • 1
  • 1
WSimpson
  • 460
  • 4
  • 7
  • `potentially be targeted for change in the future.` yes, but I don't that applies for javascript. – Aesthetic Sep 14 '16 at 10:17
  • Came here and saw all the above answers and was thinking to myself that something just looked off about the assignment. I've just been reading Clean Code by Robert C Martin and this type of assignment definitely violates the "Have no Side Effects" rule...while the author himself states that his book is only one of many techniques for generating good code, I was still surprised that no one else objected to this kind of assignment. +1 – Albert Rothman Sep 20 '16 at 23:50
  • Thank you for the response. I think more people need to consider side effects when writing code, but until someone has spent a lot of time maintaining other people's code. They often don't consider it. – WSimpson Sep 27 '16 at 13:53
  • 2
    You really think that monstrosity is clearer than `a || b || c || d || e`? – devios1 Oct 16 '17 at 16:41
  • 1
    @AlbertRothman I don't see any side effects. Nothing is being mutated. It's simply a shorthand for null coalescing, which is a quite common feature in many languages. – devios1 Oct 16 '17 at 16:43
  • "Using this technique is not good practice for several reasons; however." It's basically the standard way to sanity check a functions input - have you even seen any Javascript - you do know that it lacks parameter type-hinting, right? :P – Christoffer Bubach Jul 20 '20 at 21:12
8

Return output first true value.

If all are false return last false value.

Example:-

  null || undefined || false || 0 || 'apple'  // Return apple
Arshid KV
  • 9,631
  • 3
  • 35
  • 36
5

Its called Short circuit operator.

Short-circuit evaluation says, the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression. when the first argument of the OR (||) function evaluates to true, the overall value must be true.

It could also be used to set a default value for function argument.`

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`
Vijay
  • 168
  • 3
  • 9
4

It's setting the new variable (z) to either the value of x if it's "truthy" (non-zero, a valid object/array/function/whatever it is) or y otherwise. It's a relatively common way of providing a default value in case x doesn't exist.

For example, if you have a function that takes an optional callback parameter, you could provide a default callback that doesn't do anything:

function doSomething(data, callback) {
    callback = callback || function() {};
    // do stuff with data
    callback(); // callback will always exist
}
Matthew Crumley
  • 101,441
  • 24
  • 103
  • 129
2

It means that if x is set, the value for z will be x, otherwise if y is set then its value will be set as the z's value.

it's the same as

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

It's possible because logical operators in JavaScript doesn't return boolean values but the value of the last element needed to complete the operation (in an OR sentence it would be the first non-false value, in an AND sentence it would be the last one). If the operation fails, then false is returned.

Andris
  • 27,649
  • 4
  • 34
  • 38
  • 5
    this is wrong! if (x) { z = x; } else {z = y;} if the first value is false, the second value is always assigned not depending what the value actually is. – evilpie Jun 21 '10 at 20:13
  • Except that I think it just assigns y to z if x is *false*. That's the way it works for me in FF, of course, that might be implementation dependent, too. – tvanfosson Jun 21 '10 at 20:15
  • 7
    The last part about returning false isn't true (no pun intended). If the first value is falsey, the `||` operator just returns the second value, regardless of whether it's truthy or not. – Matthew Crumley Jun 21 '10 at 20:15
  • -1. Your equivalent code snippet is accurate, but the important point is that `z` gets set to the value of `x` if that value is *truthy*. Otherwise it gets set to the value of `y`. This means that if `x` is set to, for example, `0`, or the empty string `""`, this doesn’t do what you say, since those values are *falsy*. – Daniel Cassidy Sep 27 '10 at 16:56
1

According to the Bill Higgins' Blog post; the Javascript logical OR assignment idiom (Feb. 2007), this behavior is true as of v1.2 (at least)

He also suggests another use for it (quoted): "lightweight normalization of cross-browser differences"

// determine upon which element a Javascript event (e) occurred
var target = /*w3c*/ e.target || /*IE*/ e.srcElement;
1

It will evaluate X and, if X is not null, the empty string, or 0 (logical false), then it will assign it to z. If X is null, the empty string, or 0 (logical false), then it will assign y to z.

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

Will output 'bob';

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • 1
    You should clarify what you mean by ‘empty’. Empty strings coerce to `false`, but empty arrays or objects coerce to `true`. – Daniel Cassidy Sep 27 '10 at 16:58
  • @Daniel "null, empty, or 0" -- null would apply with respect to arrays and objects. Point taken, though. – tvanfosson Sep 27 '10 at 17:01