How about an `Object.from` similar to `Array.from`

const array = [{ x: 'a' }, { x: 'b' }, { x: 'c' }]

const result = Object.from(
  array, // some iterable
  ({ x }) => x, // returns object key
)

// result: { a: { x: 'a' }, b: { x: 'b' }, c: { x: 'c' } }

// couple ways of doing this currently with arrays
Object.fromEntries(array.map(item => [item.x, item]))
array.reduce((acc, item) => ({ ...acc, [item.x]: item }), {})

// or from an iterable
Object.fromEntries(
  Array.from(
    array, // some iterable
    item => [item.x, item],
  ),
)

Why would this be better than Object.fromEntries?

With Object.from, you map each value to a key, and you get to choose the key with a callback function.

To do the same thing with Object.fromEntries you first have to do some preprocessing (probably with Array.prototype.map) and you have to understand what "entries" are in order to use that function manually, which I wouldn't expect most developers to know without a bit of digging.

You can also use Array.prototype.reduce but that's quite boilerplate-y/verbose for kind of a simple task.

I don't think the ways I showed above are very concise or intuitive ways of converting an iterable to an object. If there's a better way to do it, Idk.

It's a similar concept to python's dict(iterable, key=lambda item: item.x)

It’s not quite the same but the stage 3 array grouping proposal helps these types of situation

The key difference being the resulting object always contains arrays to handle multiple items mapping to the same key. Rather than silently overriding each other.

That's true. The only issue with that is if you used it to get separate keys for all your values, all your values would still be nested in an array looks like.

const array = [{ x: 'a' }, { x: 'b' }, { x: 'c' }]

const result = array.group(({ x }) => x);

// result: { a: [{ x: 'a' }], b: [{ x: 'b' }], c: [{ x: 'c' }] }

I think doing this with Object.fromEntries is already sufficiently clear. Learning about Object.fromEntries takes no more time than learning about Object.from would.

It's true that you'd also need to use .map, but I don't think that's enough justification for a new function on its own. We are not going to provide every combination of two facilities as its own function.

1 Like

I think Object.from is useful if it creates an object of same "shape" of source object.

e.g.

let oA = {a:1, b:2};
let oB = {a:3, b:4};

oA and oB is same shape.

Now

let oC = Object.from(oA);

Object oC has shape of oA

oC.a = 5;
oC.b = 6;

Instead of :

let oC = {};
oC.a = 5;
oC.b = 6;

, Object.from should be faster.

Reference: https://v8.dev/blog/fast-properties

const oC = {...oA};

Or

const oC = Object.assign({}, oA);
1 Like