The short-circuiting logical-or connective || is often used as a default operator. If an expression would produce a falsy value, then appending || and another expression will fill in a default value instead.
possible_value || default_value
This works well for things like text fields, where the value from an empty field is easily replaced with a default value.
This is also used with parameters and object members, but there is a problem. With parameters and object members, the only falsy value of interest usually is undefined. Unfortunately, the number 0 is also a falsy value, which can lead to an unintended replacement with the default value.
We propose that a default operator ?? be added. It is a short-circuiting operator. If the first operand evaluates to a value other than undefined, then the result is the first operand and the second operand is not evaluated. But if the result of evaluating the first operand is undefined, then the second operand is evaluated and used as the result.
possible_value ?? default_value
is a short form of
possible_value !== undefined ? possible_value : default_value
but with possible_value evaluated exactly once.
For convenience, we propose adding an ??= assignment operator:
variable ??= default_value; // variable = variable ?? default_value
As with the existing assignment operators, the Reference internal type instance evaluated from the left-hand side variable is evaluated once, and used via GetValue in the expansion on the right of =.
— Douglas Crockford 2011/02/13 00:48 — Brendan Eich 2012/06/17 18:52
The production ConditionalExpression : LogicalORExpression ?? AssignmentExpression is evaluated as follows:
The production AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression is evaluated as follows:
— Brendan Eich 2012/06/17 18:52
Ryan Florence provided some good examples of pain points that exist today, that could be mitigated by the default operator:
https://mail.mozilla.org/pipermail/es-discuss/2012-June/023356.html
var events = { _callbacks: {}, on: function (topic, callback) { (this._callbacks[topic] ??= []).push(callback); ... }, ... };
function ajaxWithError (settings) { settings.method ??= 'POST'; settings.elementPosition ??= this._getElementPositions(); settings.somethingWithInitialization ??= (function(){ var thing = new Thing(); thing.foo = settings.foo; return thing; })(); ... };
— Rick Waldron 2012/06/12 17:08
||= deserve another look, even though it would be a new (Ruby-like) idiom?= (assignment operator) semantics, rather avoids assigning L = L in truthy-L case.null be equated to undefined? Need more source code surveys.