Object.enumerableKeys / Object.enumerableValues / Object.enumerableEntries
Rationale
Following the rationale in Object.values and Object.entries proposal, all these methods are useful to obtain an array of keys, values, and key/value pairs (what the spec calls “entries”) from an object, for the purposes of iteration or serialization.
They are largely used by libraries like Lodash. The method names are based on Lodash’s _.keysIn
,
_.valuesIn
, and _.forIn
methods, which were inspired by
for…in,
and JS Object.{keys, values, entries}
.
The return is similar to the current triplet {keys, values, entries}
in Object
,
the main difference is the enumerating the properties in the prototype chain, like
the for…in
loop. Object.enumerableKeys
has got an extra motivation after
Reflect.enumerate
removal, following the removal of the [[Enumerate]]
internal method.
The current methods are consistent with Reflect.enumerate
and the for…in
loop
as it only list String-valued keys of enumerable properties, ignoring any symbol
keys.
array vs iterator
These additions are complementary to the existing Object.keys
, Object.values
,
and Object.entries
. They are basically the same methods including inherited
String-value keys.
Use cases
With a spread use of prototypal chain in objects, the serialization of own and inherited entries is valuable. The large use adoption of Lodash methods is a good use case.
jQuery's $.extend
and
$.fn.extend
and Underscore/Lodash
_.extend
/_.assignIn
and
_.defaults
iterate over own and inherited
enumerable properties. In the case of Lodash, keysIn
is used to get the property names to iterate over. It's also used in Underscore
_.functions
and Lodash's _.functionsIn
.
The use of Object.enumerableValues
can be mapped to the use of values
which is used
in library helpers like Underscore/Lodash includes
for seeing if a value is in an object or sample
which grabs a random value from an object.
Node.js DB packages like Mongoose use some of these Lodash methods when working with data objects.
Lodash's _.toPlainObject
which
flattens inherited properties to own properties of a new object. This is handy
for working with Object.assign
and keysIn
is used to implement that.
Examples
// Given the current variables:
var results;
var iterSuper = {
foo: 42
};
var iter = Object.create( iterSuper );
iter.bar = 43;
Object.enumerableKeys( O )
// Before
results = [];
for ( let x in iter ) {
results.push( x );
}
results; // [ "foo", "bar" ]
// After
results = Object.enumerableKeys( iter );
results; // [ "foo", "bar" ] (same order as for loop)
Object.enumerableValues( O )
// Before
results = [];
for ( let x in iter ) {
results.push( iter[ x ] );
}
results; // [ 42, 43 ]
// After
results = Object.enumerableValues( iter );
results; // [ 42, 43 ] (same order as for loop)
Object.enumerableEntries( O )
// Before
results = [];
for ( let x in iter ) {
results.push( [ x, iter[ x ] ] );
}
results; // [ [ "foo", 42 ], [ "bar", 43 ] ]
// After
results = Object.enumerableEntries( iter );
results; // [ [ "foo", 42 ], [ "bar", 43 ] ] (same order as for loop)
Spec
Object.enumerableKeys( O )
- Let obj be ? ToObject(O).
- Let nameList be ? EnumerableProperties(obj, "key").
- Return CreateArrayFromList(nameList).
Object.enumerableValues( O )
- Let obj be ? ToObject(O).
- Let nameList be ? EnumerableProperties(obj, "value").
- Return CreateArrayFromList(nameList).
Object.enumerableEntries( O )
- Let obj be ? ToObject(O).
- Let nameList be ? EnumerableProperties(obj, "key+value").
- Return CreateArrayFromList(nameList).
EnumerableProperties
When the abstract operation EnumerableProperties is called with Object O and String kind the following steps are taken:
- Assert: Type(O) is Object.
- Let iterator be ? EnumerateObjectProperties(obj).
- Let properties be a new empty list.
- Repeat
- Let next be ? IteratorStep(iterator)
- If next is false, return properties.
- Let nextArg be ? IteratorValue(next).
- If kind is "key", append nextArg as the last element of properties.
- Else, 1. Let value be ? Get(O, key). 1. If kind is "value", append value to properties. 1. Else,
- Assert: kind is "key+value".
- Let entry be CreateArrayFromList(« key, value »).
- Append entry to properties.