I recently faced issues where I couldn't use .map on iterable objects and had to convert them to arrays with either Object.values or Array.from
I seem to get same result in both cases, so I'm wondering what the difference is. In which case do you use one over the other?
CodePudding user response:
It's not true in the general case that you'll get the same result from Array.from(x)
and Object.values(x)
when x
is an iterable object. In fact, it's fairly rare (just arrays and array-likes¹ that hide their length
property by making it non-enumerable or inheriting it and don't have any other own, enumerable properties). Array.from
will loop through the iterable object using iteration; Object.values
will loop through the object looking for own, enumerable properties. For an array that doesn't have any non-array properties, that ends up being the same thing, but it's not true in the general case.
In the general case, Array.from
and Object.values
do very different things and have different results:
Array.from
creates an array from any iterable or array-like object (an object with alength
and index properties like 0 and 1).Object.values
creates an array of the values of an object's own enumerable properties. The object doesn't have to be iterable (Object.values
doesn't even look to see if it is.)Array.from
accepts a second argument, a function that can be used to map the values from the iterable/array-like into new values for the array.
Here's an example where Object.values
gets []
(because the Set
has no own enumerable properties) but Array.from
gets [1, 2, 3]
(because the Set
's iterator provides those three values):
const x = new Set([1, 2, 3]);
// Shows an empty array
console.dir(Object.values(x));
// Shows [1, 2, 3]
console.dir(Array.from(x));
Conversely, here's one where Object.values
returns [1, 2, 3]
because the object has those as own enumerable properties, but Array.from
returns []
because the object is neither iterable nor array-like:
const x = {a: 1, b: 2, c: 3};
// Shows [1, 2, 3];
console.dir(Object.values(x));
// Shows []
console.dir(Array.from(x));
¹ An array-like object is an object with:
- A
length
property - Properties named with strings that are numbers in the normal decimal form for the values
0
throughlength - 1
(but there can be gaps).
For instance, this is an array-like object:
const obj = {0: "zero", 1: "one", length: 2};
(I've used number literals for the property names, but they'll be converted to string.)
Note that that object will give you different results for Array.from
and Object.values
because length
is an own, inherited property.
CodePudding user response:
Array.from
creates a new array, usually from another array, but can also be used on Set
. It also has a second arguments, that allows to map each element to another value.
Object.values
on the other hand creates a new array
with the values from the supplied object.
I'm not exactly sure why you say they do the same thing, as they don't. Except maybe the fac that you end up with an array as the results. Take this example for instance:
Object.values({a: 2, b:3}) // will return [2, 3]
on the other hand
Array.from({a: 2, b:3}) // will return [], as an object is not an array-like object