# New: Logical Assignment Operators

Since I finished the book, a new proposal has reached Stage 3 4 (as of the July 2020 meeting): Logical Assignment Operators. It adds three new compound assignment operators to the language: `||=`, `&&=`, and `??=`. At first glance it seems like these would be just like the existing compound assignment operators (`+=`, `-=`, and such), but they have a twist: They short-circuit (even the assignment part).

First let's look at basic operation, then we'll come back to short-circuiting.

## Basic Operation

Like their mathematical cousins, the new operators combine an operation with an assignment. `||=` (the proposal calls it "Or Or Equals") combines `||` with assigning back to the left-hand side:

``````let left = false;
let right = true;
left ||= right;
console.log(left); // true``````

Similarly, "And And Equals" does the same for `&&`:

``````let left = true;
let right = false;
left &&= right
console.log(left); // false``````

And "QQ Equals" (as the proposal calls it; I prefer "Nullish Equals") does it for nullish coalescing (see Chapter 17 of the book):

``````let left = undefined;
let right = 42;
left ??= right;
console.log(left); // 42``````

So far, so simple. Now the twist: Depending on the value of the left-hand side, the assignment part of that may not happen at all thanks to short-circuiting.

## Short Circuiting

You may know that the logical operators short-circuit their operation. For instance, `left || right` doesn't evaluate `right` at all if `left` is already truthy; there's no need to evaluate the right-hand side, the operation will result in `left`'s value. If the right-hand operand involved side-effects (perhaps it's a function call), the fact it isn't evaluated is important.

The logical assignment operators short-circuit too, but they don't just skip evaluating `right`'s value, they also skip the assignment back to `left`! After all, there's no point in writing `left`'s own value back to it. You can see that in practice if you're using an accessor property:

``````const obj = {
_left: true,
get left() {
const result = this._left;
console.log(`Getting left: \${result}`);
return result;
},
set left(value) {
console.log(`Setting left: \${value}`);
this._left = value;
}
}

// Using a simple assignment and `||`:
obj.left = obj.left || false;
// =>
// Getting left: true
// Setting left: true

// Using compound assignment:
obj.left ||= false;
// =>
// Getting left: true``````

Notice there's no "Setting" log line; that's because the setter wasn't called, because the operation short-circuited.

Details in the proposal of course, but here's the fundamental logic (slightly simplified) for `left op= right` where `op` is `||`, `&&`, or `??`:

1. Get the Reference for `left` and call it lref. (A Reference is basically a spec mechanism for identifying where a value came from, such as a variable, parameter, property, etc.)
2. Get the value of lref and remember it as lvalue
3. Perform the operation that `op` would perform on lvalue to determine whether to short-circuit; if short-circuiting, return lvalue and skip the remaining steps
4. Get the Reference for `right`, get its value, and remember the value as rvalue
5. Store rvalue in lref
6. Return rvalue

For `||=` Step 3 is:

1. Convert lvalue to boolean; if the result is `true`, return lvalue and skip the remaining steps

For `&&=` it's the same but with `false`:

1. Convert lvalue to boolean; if the result is `false`, return lvalue and skip the remaining steps

For `??=` it's just a straight check:

1. If lvalue is neither `undefined` nor `null`, return lvalue and skip the remaining steps

There were arguments on both sides of whether the assignment part should be short-circuited. Concerns about short-circuiting came from at least two perspectives:

• It makes these operators different from the mathematical compound assignment operators, which never short-circuit; `left += 0` always writes back to `left`, which is something you can observe if it's an accessor property.
• It makes the naïve explanation "`left ||= right` is basically `left = left || right`" incorrect, since `left = left || right` will always write back to `left` but `left ||= right` may not; which, again, is observable (for instance, if `left` is an accessor).

Countering those concerns:

• The `||`, `&&`, and `??` operators are already different from mathematical operators. `||`, `&&`, and `??` short-circuit; mathematical operators don't. Since they're already different, it's reasonable that the compound assignment versions of them are different as well.
• The naïve explanation is already incorrect. `left += right` is observably different from `left = left + right` even though it always writes back to `left`: In the compound form, `left` is only evaluated once, but in the simple form, `left` is evaluated twice. That's observable if `left` isn't just a simple variable or property reference, but something with a side-effect, like `counter[index++] += 42`, which is quite a bit different from `counter[index++] = counter[index++] + 42`.
• Ruby, C#, and CoffeeScript all have these operators, and all short-circuit them. Ruby's have had this behavior for well over a decade. Making JavaScript different in this regard would break people's intuition coming from other languages with similar operators.

## Destructuring...?

You may be wondering, as I was, whether this is valid:

``````// Is this valid...?
({ left } ??= obj); // Meaning something like `left = left ?? obj.left```````

No, it isn't. Which is consistent with how the mathematical compound operators are handled. For now, the assignment target must be simple, not destructuring.

I don't know why I never thought to wonder about that with mathematical compound assignments, but I never did; and yet, I immediately wondered about it with these logical ones, particularly `??=`. That said, the cognitive load of understanding that destructuring nullish coalescing logical assignment is...well...pretty high. :-)

What I didn't think to ask, though, was a question asked by others in a couple of proposal issues, such as #7: Can you use `??=` to provide a default value for a destructuring target when the source value is `null` (rather than only when it's `undefined`), like this?

``````// Can you do this...?
const obj = { value: null };
const {value ??= "default"} = obj;
console.log(value); // "default"``````

The answer is no, you can't, but not because people necessarily thought it was a bad idea; it's just that destructuring patterns are a completely different beast from compound assignment operators, so it was out of scope for this proposal. It could be the subject of a future proposal, though...

## Wrapup

I'm really glad to see these new operators, and glad the semantics ended up the way they did. I'll definitely be using them.

Happy coding!

Have a question about or comment on this post? Tweet me!