ECMAScript recently added an interesting new proposal to add the following three compound assignment operators:

  • a ||= b
  • a &&= b
  • a ?? = b

Tc39. Es /proposal-lo…

First, let’s look at the existing operators.

The compound assignment operator

JavaScript already supports compound assignment operators:

  • Basic arithmetic operators: +=, -=, *=, /=, %=, *=
  • According to an assignment operator: & =, ^ =, | =
  • Shift assignment operators: <<=, >>=, >>>=

The above compound operators follow the following rules:

  • Expression: A op= b
  • Equivalent to: A = a op b

For example: A &= b == “A = a & b

Place a and B bitwise and then assign the result to A

Short-circuit operator

Before we try out the proposed compound operator, we need to understand the “short-circuit operator”.

Logical operators: | |, &&,?????? Are short-circuit operators whose second operand depends on the first operand failing to produce a result:

The operator Is equivalent to
a || b a ? a : b
a && b ! a ? a : b
a ?? b a ! == undefined && a ! == null ? a : b

The logical operator of the latest proposal

The logical operators of the new proposal behave a little differently from the existing compound operators:

The assignment operator Is equivalent to
a ||= b a || (a = b)
a &&= b a && (a = b)
a ?? = b a ?? (a = b)

Why a | | = b is equivalent to a | | (a = b)?

According to our understanding of short circuit of the operators, should be equal to: a = a | | b, why not?

Let’s look at the differences between the two:

  • A | | (a = b) : the expression means Only when a is false, will be assigned to a b

  • A = a | | b: a assigned to a first, and then with b or operation.

To sum up, there is a significant difference in meaning between the two.

Next, let’s look at the possible application scenarios for the new proposal assignment expression.

Application scenario: Using?? = Adds missing attributes to the object

const books = [
  {
    isbn: '123'.  },
  {
 title: 'ECMAScript Language Specification'. isbn: '456'. }, ];  // Add a title to the books object if there is no title for (const book of books) { book.title ?? ='(Untitled)'; } // The result is equal. assert.deepEqual(  books,  [  {  isbn: '123'. title: '(Untitled)'. },  {  title: 'ECMAScript Language Specification'. isbn: '456'. },  ]); Copy the code

Application scenario: Use &&= to obtain global attributes

const globalSettings = {
    title:'ECMAScript Language Specification'.    isbn:"456"
};
const params={
 title:true } // Set global properties for params. If params needs to obtain any properties, set the parameter to true. for (const key of params) {  params.key &&= globalSettings[key]; } // The result is equal. assert.deepEqual(  params,  {  title:'ECMAScript Language Specification'  } Copy the code

Application scenarios: use the | | = decomposition expression

The following function returns an expression expanded across multiple lines:

function canContainNumber(value) {
  return typeof value === 'number'
    || typeof value === 'bigint'
    || typeof value === 'string'
  ;
} assert.equal(canContainNumber(' '), true); assert.equal(canContainNumber(Symbol()), false); Copy the code

The above functions can be written as follows:

function canContainNumber(value) {
  let result = false;
  result ||= typeof value === 'number';
  result ||= typeof value === 'bigint';
  result ||= typeof value === 'string';
 return result; } Copy the code