Conditional object properties

# Luke Mitchell (8 years ago)

I often come across a situation where I wish to extend an object (usually an argument for an API request) if a particular condition is satisfied, such as the presence of a function parameter. Currently the only way to do this is by assigning the object to a variable, checking the condition using an if statement and then extending the object. I am proposing the inclusion of an operator that allows a property to be included, subject to a particular condition, inside the object definition.

The operator looks like this:

let obj = {
  cond ? prop: value
};

The operator could also be used with a block statement, allowing multiple properties to be included:

let obj = {
  cond ? {
    prop1: value1,
    prop2: value2
  }
};

I have created a draft proposal and would love to hear any thoughts you have on the matter. You can find it on my GitHub, at the link below.

lukem512/proposal-condition-property-definitions

Kind , Luke

# Isiah Meadows (8 years ago)

What benefit would this bring over imperatively adding properties?

# kdex (8 years ago)

I'd imagine that from an engine point of view, this means that fewer object shapes land in memory, at least for v8.

Reducing the number of object shapes currently boils down to using an object literal and setting the properties to value || null instead of extending the object with new properties imperatively.

# Isiah Meadows (8 years ago)

That's not likely to make any serious performance difference with an ajax call. And in tight loops, I try avoid conditionals and object creation anyways, to avoid branch prediction fails (in both the engine and CPU) and costly allocation. (Most engines only do a limited form of pooling for faster GC.)

# Luke Mitchell (8 years ago)

Aside from performance, the operator also leads to denser code which is easier to write. Talking to my colleagues, I was told that two of them could have used it already this morning!

Luke

# Boris Zbarsky (8 years ago)

On 11/2/16 9:04 AM, kdex wrote:

I'd imagine that from an engine point of view, this means that fewer object shapes land in memory, at least for v8.

I'm pretty sure it means nothing of the sort in SpiderMonkey (in terms of memory usage, not in terms of object shapes that flow through subsequent shape guards), for what it's worth. I'm not sure it's worth adding things to the standard just to work around implementation quirks of a specific implementation.

No opinion on the ergonomics argument.

Reducing the number of object shapes currently boils down to using an object literal and setting the properties to value || null instead of extending the object with new properties imperatively.

This actually creates more object shapes in SpiderMonkey, I believe, though fewer shapes that flow through code locations. So it depends on whether you're trying to optimize memory usage or performance. And of course on whether you're tuning to a particular engine's current implementation strategy...

# Reinis Ivanovs (8 years ago)

No need for new syntax, you can just do this:

{...cond ? {prop: value} : null}

I find it about the same in readability.

# Luke Mitchell (8 years ago)

That works, although you have to add parenthesis. It's a nice solution but it is still a bit more verbose with the spread, the parenthesis and the : null.

let cond = true;
let obj = {
  prop1: 'hello',
  ...(cond ? {prop2: 'world'} : null)};
// { prop1: 'hello', prop2: 'world' }

cond = false;
let obj = {
  prop1: 'hello',
  ...(cond ? {prop2: 'world'} : null)};
// { prop1: 'hello' }
# Bergi (8 years ago)

Luke Mitchell schrieb:

Hi all,

I often come across a situation where I wish to extend an object (usually an argument for an API request) if a particular condition is satisfied, such as the presence of a function parameter. Currently the only way to do this is by assigning the object to a variable, checking the condition using an if statement and then extending the object. I am proposing the inclusion of an operator that allows a property to be included, subject to a particular condition, inside the object definition.

You can already do

let obj = Object.assign({
     …
}, cond ? { prop: value } : null);

Or depending on your condition, also just cond && { prop: value }.

The object spread proposal will achieve the same, without the need for any extra operator.

# Reinis Ivanovs (8 years ago)

It works in Babel without the parenthesis.