New proposal of es: double question mark operator

Time:2019-12-21

Abstract:Simple and practical new features.

  • New proposal of es: double question mark operator
  • Translator: front-end wit

This article mainly talks aboutGabriel IsenbergThe ES proposal “nullish coalescing for JavaScript” was written. It puts forward??replace||And provides a default value. Let’s call this proposalDouble question mark operator, if you have a good name, please leave a message to discuss.

1. overview

Double question mark??The operator of||Similarly, if the given variable value isnullperhapsundefined, the default value just after using the double question mark, otherwise use the variable value.

As follows:

> undefined ?? 'default'
    'default'
    > null ?? 'default'
    'default'
    > false ?? 'default'
    false
    > '' ?? 'default'
    ''
    > 0 ?? 'default'
    0

2. Early operation symbols

Let’s give you an example||Operation, the following two equations are equivalent:

a || b
    a ? a : b

IfaIs the truth value, then returna, otherwise returnb

This enables the use of||It is possible to specify a default value, which will be used if the actual value is false:

const result = actualValue || defaultValue;
    function getTitle(fileDesc) {
      return fileDesc.title || '(Untitled)';
    }
    const files = [
      {path: 'index.html', title: 'Home'},
      {path: 'tmp.html'},
    ];
    assert.deepEqual(
      files.map(f => getTitle(f)),
      ['Home', '(Untitled)']);

Please note that only in actual valueundefinedOr fornullThe default value should only be used, which is valid becauseundefinedandnullAll false (virtual):

> undefined || 'default'
    'default'
    > null || 'default'
    'default'

Unfortunately, if the actual value is another virtual value, the default value is also used:

> false || 'default'
    'default'
    > '' || 'default'
    'default'
    > 0 || 'default'
    'default'

So, thisgetTitle()Not always working:

assert.equal(
      getTitle({path: 'empty.html', title: ''}),
      '(Untitled)');

3. Use double question mark operator to solve the problem of|operation

??Mainly used to solve||The following two expressions are equivalent for some problems of operation symbols:

a ?? b
    a !== undefined && a !== null ? a : b

The default values are provided as follows:

const result = actualValue ?? defaultValue;

aboutundefinedandnull??How operators work and||Same operator

> undefined ?? 'default'
    'default'
    > null ?? 'default'
    'default'

exceptundefinedandnullOther virtual values of,??The default value is not returned.

> false ?? 'default'
    false
    > '' ?? 'default'
    ''
    > 0 ?? 'default'
    0

Use??To rewritegetTitle():

function getTitle(fileDesc) {
      return fileDesc.title ?? '(Untitled)';
    }

Now usefileDescCall it, its.titleIt is an empty string, which can still work as expected:

assert.equal(
      getTitle({path: 'empty.html', title: ''}),
      '');

3.1 default values given by deconstruction

Besides using??togetTitleAdd default value, we can also give default value through deconstruction:

function getTitle({title = '(Untitled)'}) {
      return title;
    }

3.2 practical examples of using? Operation symbols

As a practical example, let’s use??To simplify the following functions.

function countMatches(regex, str) {
      if (!regex.global) {
        throw new Error('Regular expression must have flag /g: ' + regex);
      }
      const matchResult = str.match(regex); // null or Array
      if (matchResult === null) {
        return 0;
      } else {
        return matchResult.length;
      }
    }
    
    assert.equal(
      countMatches(/a/g, 'ababa'), 3);
    assert.equal(
      countMatches(/b/g, 'ababa'), 2);
    assert.equal(
      countMatches(/x/g, 'ababa'), 0);
    
    // Flag /g is missing
    assert.throws(
      () => countMatches(/a/, 'ababa'), Error);

Use??After operating the symbols, simplify as follows:

function countMatches(regex, str) {
      if (!regex.global) {
        throw new Error('Regular expression must have flag /g: ' + regex);
      }
      return (str.match(regex) ?? []).length;
    }

3.3 double question mark (?) operator and optional chain (?)

Double question mark (??)Is proposed to supplement the optional chain(?), take a look at the scenario of the two brothers using together (line a):

const persons = [
      {
        surname: 'Zoe',
        address: {
          street: {
            name: 'Sesame Street',
            number: '123',
          },
        },
      },
      {
        surname: 'Mariner',
      },
      {
        surname: 'Carmen',
        address: {
        },
      },
    ];
    
    const streetNames = persons.map(
      p => p.address?.street?.name ?? '(no name)'); // (A)
    assert.deepEqual(
      streetNames, ['Sesame Street', '(no name)', '(no name)']
    );

4. compatibility

You can view it through ECMAScript next compatibility table??Support.

The bugs that may exist after the code is deployed cannot be known in real time. In order to solve these bugs afterwards, a lot of time has been spent on log debugging. In this way, we recommend a good bug monitoring tool fundebug.

About fundebug

Fundebug focuses on real-time BUG monitoring of JavaScript, WeChat applets, WeChat games, Alipay applets, React Native, Node.js and Java online applications. Since the official launch on the double 11 of 2016, fundebug has handled 2 billion + error events in total. Paying customers include sunshine insurance, walnut programming, litchi FM, 1-on-1 leader, micro pulse, qingtuan club and many other brand enterprises. Welcome to try it for free!