A Stage 1 proposal to combine Logical Operators and Assignment Expressions
Switch branches/tags
Nothing to show
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
README.md spelling fix (#4) Apr 2, 2018

README.md

proposal-logical-assignment

A Stage 1 proposal to combine Logical Operators and Assignment Expressions:

// "Or Or Equals" (or, the Mallet operator :wink:)
a ||= b;
a || (a = b);

// "And And Equals"
a &&= b;
a && (a = b);

// Eventually....
// "QQ Equals"
a ??= b;
a ?? (a = b);

Motivation

Convenience operators, inspired by Ruby's. We already have a dozen mathematical assignment operators, but we don't have ones for the often used logical operators.

function example(a = b) {
  // Default assignment only works for `undefined`.
  // But I want any falsey to default
  if (!a) {
    a = b;
  }
}

function numeric(a = b) {
  // Maybe I want to keep numeric 0, but default nullish
  if (a == null) {
    a = b;
  }
}

If statements work, but terseness would be nice.

function example(a = b) {
  // Ok, but it triggers setter.
  a = a || b;

  // No setter, but sometimes flagged as a lint error!
  a || (a = b);
}

With this, we get terseness and we don't have to suffer from setter calls.

Semantics

The logical assignment operators function a bit differently than their mathematical assignment friends. While math assignment operators always trigger a set operation, logical assignment embraces their short-circuiting semantics to avoid it when possible.

let x = 0;
const obj = {
  get x() {
    return x;
  },
  
  set x(value) {
    console.log('setter called');
    x = value;
  }
};

// This always logs "setter called"
obj.x += 1;
assert.equal(obj.x, 1);

// Logical operators do not call setters unnecessarily
// This will not log.
obj.x ||= 2;
assert.equal(obj.x, 1);

// But setters are called if the operator does not short circuit
// "setter called"
obj.x &&= 3;
assert.equal(obj.x, 3);

Related