-1

The specific example I have will increment obj[s] if it's truthy (has a value), and if it's falsey (doesn't exist in the object yet) it will set it equal to 1 and thus add it to the object.

But what I'm asking about, in general, looks like:

something = doIfTruthy || doIfFalsey

I'm thinking it must have a name, just like how we call this "ternary or conditional operator"

something = condition? ifTrue: ifFalse 

I'd like to be able to refer to it by a proper name in my notes. Right now I'm just calling it "exploit truthy/falsey" because that's how I use it.

I'm also wondering what you call this kind of expression, because it's similar:

something = condition && ifTrue
Laurie
  • 1
  • 1
    There isn't a specific name. It uses an OR, so it's technically an OR expression but might also be called "assignment with fallback" if you wish and most people who know JS would understand you. – VLAZ Oct 26 '21 at 05:35
  • Related: [What does "var FOO = FOO || {}" (assign a variable or an empty object to that variable) mean in Javascript?](/q/6439579/4642212). – Sebastian Simon Oct 26 '21 at 06:35
  • They're just called "logical operators", and what you "exploit" is their short-circuit behaviour. Also notice that doing side effects in their operand expressions is a bad practice, better use `if` statements for that. Or, in your particular example, `obj[s] = (obj[s] ?? 0) + 1;` – Bergi Oct 26 '21 at 07:13
  • Oh that's interesting, because originally I had obj[s] = (obj[s] ?? 0) + 1; but I was told by an instructor to use the method I have in the original question. I'm glad to know my original method was better. – Laurie Oct 26 '21 at 16:13

2 Answers2

0

You may refer to this page on MDN for more info on operators, but the gist of what you're asking is:

A || B

is called the "Logical OR" operator, where it will execute expressions left to right until it finds a truthy one, returning the 1st truthy expression.

A && B

is called the "Logical AND" operator, where it will execute expressions left to right until it finds a falsy one, returning the last truthy expression.

Side note:

I personally wouldn't recommend following in the code author's footsteps writing things like obj[s] = ++obj[s] || 1, as even though it's concise, it takes some reading to understand. Consider something like:

obj[s] ||= 0;
++obj[s];

Or:

obj[s] = (obj[s] || 0) + 1;

Or simply:

if (typeof obj[s] !== 'number')
  obj[s] = 0;
++obj[s];
jason.
  • 319
  • 1
  • 7
  • You might even want to use `??` instead of `||` – Bergi Oct 26 '21 at 07:14
  • 1
    That's interesting! As I commented above I originally had obj[s] = (obj[s] || 0) + 1; and then was advised by an instructor to use the method in my question. I think some people think it's "leet" to make everything minimalistic, but I'm in favor of legible code. I'm glad I'm right to think this way! – Laurie Oct 26 '21 at 16:15
0

For || operations, JS will return the FIRST "truthy" value it finds (reading left-to-right):

var bob = false || undefined ||  0  ||  null || "hi"
//          ^          ^         ^      ^        ^
//          nope       nope      nope   nope     yip
//
// => bob = "hi"

// --------------
// breaking
// --------------
var bob = false || "hi" ||  0  ||  null || undefined
//          ^       ^
//          nope    yip <-- stops here
//                          the rest are ignored
//
// => bob = "hi"

Another trick is to use the && (and) to ensure something exists before accessing it.

For && operations, JS will return the LAST "truthy" value it finds (reading left-to-right).

For example if you're trying to read a property from a multi-level object.

var obj = {
        foo : {
            bar : "hi"
        }
    }

var bob = obj && obj.foo && obj.foo.bar;
//          ^        ^              ^
//          yip      yip            use this
//
// => bob = "hi"

// --------------
// breaking:
// --------------
var bob = obj && obj.foo && obj.foo.sally && obj.foo.bar;
//        ^          ^              ^
//        yip        yip            nope  <-- stops here, 
//                   ^                        and returns the last "yip"
//                   |                        the rest are ignored   |
//                   '-----------------------------------------------'
//
// => bob = obj.foo

Both || and && operations are read left-to-right... so you can have things that might normally throw errors toward the right side, since JS will simply stop reading left-to-right once it detects a truthy/falsey value.

bob
  • 7,539
  • 2
  • 46
  • 42