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