Logical Assignment Operators

Merry Christmas! I'm getting this blog post in a little under the wire. I had started a little series on ES2021 features, which includes the .replaceAll() String Method, Private Class Methods, Private Accessors, and Promise.any(). However, I had a little bit of a panic as I started writing Promise.any(). I had intended on doing a larger series focusing on JavaScript Promises, touching on what Promises are, the various states of Promises, and their available methods. But as I faced writing about Promise.any() with none of those other posts written, it was clear to me I finally needed to tackle the larger Promise ecosystem in order to do the new ES2021 feature justice. Hence the series that I just wrapped, which includes Promise, Promise.all(), Promise.allSettled(), Promise.any(), Promise.race(), Promise.reject(), and Promise.resolve().

All of this is a roundabout way of saying that I'm finally wrapping up my ES2021 blog post series with this post. The only things I will not have covered are WeakRef and Finalizers. These topics are related to how the JavaScript language does garbage collection, and to be frank I think that's a topic that is well beyond my current grasp. Rather than write about something I have absolutely no reference for or thoughts about when I might use it, I'm just going to avoid it for now. Maybe I'll visit garbage collection at a future date. Wow, I'm rambling again. Okay, onto Logical Assignment Operators.

Review: Logical Operators, Nullish Coalescing Operator, and Assignment Operators

Before getting into Logical Assignment Operators, it would be useful to understand the operators that they are built on.

Logical Operators

Logical Operators are used to determine logic between variables and values. Let's say we have two variables, x = 100 and y = 25.

The && operator represents "and". Let's take a look at it in practice:

const x = 100;
const y = 25;

console.log(x < 150 && y > 15);
// Expected result: true

The statement x < 150 && y > 15 is evaluating whether the value of x is less than 150 and (&&) the value of y is greater than 15.

The || operator represents "or". Here's an example:

const x = 100;
const y = 25;

console.log(x === 150 || y === 15);
// Expected result: false

The statement x === 150 || y === 15 is evaluating whether the value of x is strictly equal to 150 or (||) the value of y is equal to 15. In this case, neither expression evaluates to true, so the entire statement evaluates to false.

The last Logical Operator is the ! operator, which represents "not":

const x = 100;
const y = 25;

console.log(!(x === y));
// Expected result: true

The statement !(x === y) is evaluating whether the value of x is not (!) equal to y (or to be more technically correct, the opposite value of whether x is strictly equal to y). 100 is not equal to 25, so this statement evaluates to true.

Nullish Coalescing Operator

I touched on the Nullish Coalescing Operator briefly in my post undefined vs null. In the interest of not duplicating work, I'll just copy that content here:

The Null Coalescing Operator is represented by two question marks (??), which separates two expressions. If the first, left hand, expression is Nullish (i.e. either undefined or null), then the second, right hand, expression gets returned. If the first, left hand, expression is anything other than undefined or null, then that is the expression that gets returned.

Here's an example:

const nullThing = null;
const falsyThing = "";
const string = "Here's a string";

const firstTest = nullThing ?? string;
console.log(firstTest);
// Expected result: "Here's a string"

const secondTest = falsyThing ?? string;
console.log(secondTest);
// Expected result: ""

In the case of firstTest, the left hand expression is a null value, so the right hand expression gets returned.

In the case of secondTest, the left hand expression, an empty string, is a Falsy Value, but not undefined or null, so the Nullish Coalescing Operator returns the empty string.

Assignment Operators

The last set of operators I want to review before getting into the new stuff is Assignment Operators. Assignment Operators assign a value to its left operand based on the value of its right operand.

The = is called the Simple Assignment Operator and is probably one of the most widely used features in the language. In most cases, it creates a name space in memory for the left operand and assigns the value of the right operand to that name space:

const person = "Joey";

There are, however, much more complicated Assignment Operators. The Addition Assignment Operator, for example (+=), adds the value of the right operand to a variable and assigns the result to the variable. For example:

let a = 100;
let b = "howdy";

console.log(a += 50); // addition operation
// Expected result: 150

console.log(b += " world"); // concatenation operation
// Expected result: "howdy world"

A similar operator is the Subtraction Assignment Operator (-=), which is less frequently used:

let a = 150;
let b = "howdy world";

console.log(a -= 50); // subtraction operation
// Expected result: 100

I'm only scratching the surface of Assignment Operators here, as there are a ton of them. I'm not sure when many would be used, and diving into things like Bitwise or Left and Right Shift are not the point of this blog post. Instead, I'm here to write about Logical Assignment Operators.

Logical Assignment Operators

ES2021 introduces three new assignment operators, known as Logical Assignment Operators, to the language. These are the Logical And Assignment Operator (&&=), the Logical Or Assignment Operator (||=), and the Logical Nullish Operator (??=). They combine logical (or nullish coalescing) operations with assignment operations.

Logical And Assignment Operator

The Logical And Assignment Operator (&&=) will check whether its left operand is truthy. If so, it will assign the value of the right operand to the left operand. If the left operand is falsy, it will leave the value of the left operand as it currently is.

let a = "howdy";
let b = false;

a &&= "hello";
console.log(a);
// Expected result: "hello";

b &&= "hello";
console.log(b);
// Expected result: false

Here is the old way of doing this kind of check and reassignment:

let a = "howdy";
let b = false;

if (a) {
  a = "hello";
}

if (b) {
  b = "hello";
}

console.log(a); // "hello"
console.log(b); // false

Logical Or Assignment Operator

The Logical Or Assignment Operator (||=) does something similar, but checks whether the left operand is falsy. If so, it will assign the value of the right operand to the left operand. If the left operand is truthy, it will leave the value of the left operand as it currently is.

let a = true;
let b = "";

a ||= "hello";
console.log(a);
// Expected result: true

b ||= "hello";
console.log(b);
// Expected result: "hello"

Here is the old way of doing this kind of check and reassignment:

let a = true;
let b = "";

if (!a) {
  a = "hello";
}

if (!b) {
  b = "hello";
}

console.log(a); // true
console.log(b); // "hello"

Logical Nullish Assignment Operator

Where the Logical And Assignment Operator and Logical Or Assignment Operator are concerned with items that are either truthy or falsy, the Logical Nullish Assignment Operator (??=) is concerned with whether the value it is checking is nullish, i.e. either null or undefined.

let a = null;
let b = false;

a ??= "howdy world";
console.log(a);
// Expected result: "howdy world";

b ??= "howdy world";
console.log(b);
// Expected result: false

Here is the old way of doing this kind of check and reassignment:

let a = null;
let b = false;

if (a === null || a === undefined) {
  a = "howdy world";
}

if (b === null || b === undefined) {
  b = "howdy world";
}

console.log(a); // "howdy world"
console.log(b); // false

So there you have it, the three new Logical Assignment Operators. In all honesty, as clever as they are, I think they really reduce readability of the code. I will definitely have to look these operators up again when I run into them in the wild (or ever decide to be a hotshot and try to use them myself), but that's what this blog post is for. Oh well.

Sources / Further Reading