12

Let's say you have a hash o of arrays; for example registered callbacks for events, when each event can have 0 or more callbacks.

Is there a better way to say this in ES6?

if (key in o) o[key].push(x); else o[key] = [x]

By "better" I mean more easily understood by other developers. Possibly more concise, but not at the expense of readability. A particular (common) problem is that o is often a longer expression, e.g. this.listeners, and repeating it three times seems suboptimal. So real code might look like this:

if (event in this.listeners)
    this.listeners[event].push(callback);
else
    this.listeners[event] = [callback];

6 Answers 6

17

By using the logical nullish assignment ??=, you could check the property and if it is undefined or null, create a new array.

(o[key] ??= []).push(x);

Older approach:

You could use a logical OR and create an array if necessary.

o[key] = o[key] || [];
o[key].push(x);
Sign up to request clarification or add additional context in comments.

Comments

4

One solution is to use a logical OR with the empty array and push to the resulting array:

(o[key] = o[key] || []).push(x);

This repeats o[key] only once.

Note the parens around the entire (o[key] = o[key] || []) assignment, whose result is o[key].

o[key] = (o[key] || []).push(x) would be incorrect, because push returns the new length of the array.

3 Comments

while that works, it is prone of misreading in the first sight, because of the assignment inside of parenthesis.
@NinaScholz: It is somewhat awkward in JS (mostly due to not having ||= "default assignment operator"), but if you're familiar with the idiom it is not too bad. Many idioms are kind of opaque at start, but become very legible with experience (e.g. the ubiquitous !! "booleaniser operator").
@Amadan, it is more the problem of the assignment operator inside of a line.
3

With the proposal logical assignment, which is currently in stage 4, you can do this:

(o[key] ||= []).push(x);

It's supported by major browsers. It is also supported by typescript (at least 4.1 and above)

Comments

1

Pretty much the same as the other answers (except that it creates a new array), but you could use the array initializer syntax:

o[key] = [...o[key] || [], x];

Comments

0

You might as well do as follows; They have minor performance differences.

o[key] = o[key] ? o[key].concat(x) : [x]
o[key] ? o[key].push(x) : o[key] = [x]
o[key] && o[key].push(x) || (o[key] = [x])

1 Comment

While these are correct, I'd prefer repeating o[key] as few times as possible (which seems to be 2).
-1
try {
    o[key].push(x)
}
catch(e) {
    //cannot push to undefined exception
    o[key] = [x]
}

1 Comment

Oh boy, using exceptions should happen only if there is a good reason for it. There is no one here...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.