Array.prototype.toObjectByProperty( element=>element.property )

Naveen Chawla naveen.chwl at gmail.com
Mon Aug 14 06:33:15 UTC 2017


For iteration, `Object.keys()` doesn't include any property in the
prototype chain like "toString" etc.
I've never been concerned about needing to allow "toString" etc. as valid
cache keys, so it's never been an issue for me so far. However, if I did in
future, I would honestly look to delete them from the Object.prototype in
my application since I never use anything in there, as long as I knew it
was safe to do so. If and only if not, then yes I might consider using a
map for those cases. But just for consistency with my other caches I might
just instead consider appending something to each object key in factored
out access methods (or just at source data) for this cache so there can't
be overlap

On Mon, 14 Aug 2017 at 01:54 Alexander Jones <alex at weej.com> wrote:

> > is nearly always a perfect fit for this
>
> The fact that it is so close to being useful, but has silly surprises like
> `'toString' in everyObject`, actually gives JS a bad reputation and
> contributes towards people being driven to other languages that have
> cleaner approaches to data types.
>
> On 13 August 2017 at 20:07, Naveen Chawla <naveen.chwl at gmail.com> wrote:
>
>> Object self-promotes because it is nearly always a perfect fit for this:
>> great performance, great literal syntax, concise access syntax. The only
>> compelling case to use a map instead is when insertion ordering is
>> required, despite the MDN article. I wouldn't oppose an equivalent
>> `Array.prototype.toMap` and `Map.fromIterable`, I would just hardly ever
>> use it
>>
>> On Sun, 13 Aug 2017, 10:33 p.m. Alexander Jones, <alex at weej.com> wrote:
>>
>>> Honestly, promoting the use of Object for this, and coupling the
>>> solution to Array, feels like the wrong direction for the language to me
>>> personally. By definition, such a map constructed from a set of homogenous
>>> values, for indexing purposes, has a clear key and value type. This
>>> guidance from MDN seems to be the right message we should be sending to
>>> developers:
>>>
>>>
>>> https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
>>>
>>> > ... ask yourself the following questions:
>>> >
>>> >  * Are keys usually unknown until run time? Do you need to look them
>>> up dynamically?
>>> >  * Do all values have the same type? Can they be used interchangeably?
>>> >  * Do you need keys that aren't strings?
>>> >  * Are key-value pairs frequently added or removed?
>>> >  * Do you have an arbitrary (easily changing) number of key-value
>>> pairs?
>>> >  * Is the collection iterated?
>>> >
>>> > If you answered 'yes' to any of those questions, that is a sign that
>>> you might want to use a Map. Contrariwise, if you have a fixed number of
>>> keys, operate on them individually, or distinguish between their usage,
>>> then you probably want to use an Object.
>>>
>>>
>>> On 13 August 2017 at 05:49, Naveen Chawla <naveen.chwl at gmail.com> wrote:
>>>
>>>> Verbosity.
>>>>
>>>> It's a task common across many project types and involves only 2
>>>> fundamental types in ES: array and object
>>>>
>>>> Compare:
>>>>
>>>> ```
>>>> const cache = array.reduce((cache, element)=>{cache[element.id] =
>>>> element; return cache;}, {});
>>>> ```
>>>>
>>>> with
>>>>
>>>> ```
>>>> const cache = array.toObject(element=>element.id);
>>>> ```
>>>>
>>>> since the signature would offer additional optional `valueFromElement`
>>>> and `startingObject` parameters nobody loses anything.
>>>>
>>>> On Sun, 13 Aug 2017 at 09:51 Barret Furton <barretfurton at gmail.com>
>>>> wrote:
>>>>
>>>>> Why not embrace `Array.prototype.reduce` instead of trying to abstract
>>>>> it away?
>>>>>
>>>>> ```js
>>>>> const identity = a => a
>>>>>
>>>>> const toObject = (fk, fv = identity) =>
>>>>>     (acc, curr) => (acc[fk(curr)] = fv(curr), acc)
>>>>>
>>>>> const arr = [['a', '1'], ['b', '2'], ['c', '3']]
>>>>>
>>>>> arr.map(a => [a[0], parseInt(a[1], 10)])
>>>>>    .filter(a => a[0] !== 'c')
>>>>>    .reduce(toObject(a => a[0]), {}) // { a: 1, b: 2 }
>>>>> ```
>>>>>
>>>>> `reduce(toObject)` clearly communicates intent, and you can even
>>>>> provide an existing object for merging.
>>>>>
>>>>> On Sat, Aug 12, 2017 at 1:58 PM, Naveen Chawla <naveen.chwl at gmail.com>
>>>>> wrote:
>>>>>
>>>>>> My proposal was `Map.fromIterable(iterable, keyFromElement[,
>>>>>> valueFromElement[, existingMap]])` so it's not meant to be symmetrical with
>>>>>> `values` anyway. It was as an equivalent of `Object.fromIterable(iterable,
>>>>>> keyFromElement[, valueFromElement[, existingObjectToUse]])` as a means to
>>>>>> construct an object's keys and values from any iterable.
>>>>>>
>>>>>> I also was just thinking that both can perfectly coexist with
>>>>>> `Array.prototype.toObject(keyFromElement[, valueFromElement])` which has
>>>>>> the advantage of chain-ability after array transformation methods (like
>>>>>> `filter` etc.). Array is such a fundamental construct that I would find
>>>>>> myself using this one the most frequently
>>>>>>
>>>>>> On Sat, 12 Aug 2017 at 21:44 Alexander Jones <alex at weej.com> wrote:
>>>>>>
>>>>>>> `Map.fromIterable` takes an iterable of values, and a key function.
>>>>>>> Would a `Map.prototype.toIterable` return only the values - that's already
>>>>>>> `Map.prototype.values`? It feels like there is a symmetry issue here.
>>>>>>> Perhaps this could be `Map.fromValues`?
>>>>>>>
>>>>>>> Worth also remembering that compressing every possible use case down
>>>>>>> to an absolute minimum has a cost if the resultant language has too many
>>>>>>> features like this. I think `new Map(...kvps)` is a general solution that
>>>>>>> is actually good enough for "indexing" purposes, and means that people only
>>>>>>> have to internalise one method of construction via iterables.
>>>>>>>
>>>>>>> That said, a helper function to allow constructing map-like objects
>>>>>>> from arbitrary iterables would maybe be a bit more composable?
>>>>>>>
>>>>>>> ```js
>>>>>>> // This works with Map, WeakMap, Immutable.Map, etc.
>>>>>>> function* keyedBy(iterable, keyFn) {
>>>>>>>   for (const element of iterable) {
>>>>>>>     yield [keyFn(element), element];
>>>>>>>   }
>>>>>>> }
>>>>>>>
>>>>>>> const allThePeople = [{name: "Joe", age: 24}, {name: "Barbara", age:
>>>>>>> 43}, ...];
>>>>>>>
>>>>>>> const index1 =
>>>>>>>   new Map(keyedBy(allThePeople, _ => _.name));
>>>>>>>
>>>>>>> // c.f.
>>>>>>> const index2 =
>>>>>>>   Map.fromValues(allThePeople, _ => _.name);
>>>>>>> ```
>>>>>>>
>>>>>>> On 11 August 2017 at 10:26, Naveen Chawla <naveen.chwl at gmail.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>> Of these, insertion ordering is the only one that may be compelling
>>>>>>>> enough to me when I require that, to overcome the disadvantages. I never
>>>>>>>> use the object prototype and I'm not convinced about the performance
>>>>>>>> aspect. I reiterate though that `Map.fromIterable(allThePeople,
>>>>>>>> person=>person.name)` is less verbose for the stated use case
>>>>>>>>
>>>>>>>> On Fri, 11 Aug 2017 at 11:55 Darien Valentine <
>>>>>>>> valentinium at gmail.com> wrote:
>>>>>>>>
>>>>>>>>> @Alexander The idea of a generalized `map` function (etc, I’m
>>>>>>>>> guessing) is
>>>>>>>>> appealing. From the way you talked about it, it sounds like there
>>>>>>>>> may have been
>>>>>>>>> past discussion on the topic. Are there any proposals for this or
>>>>>>>>> major ideas
>>>>>>>>> being batted around?
>>>>>>>>>
>>>>>>>>> > Why? What's the advantage? You lose at least the square bracket
>>>>>>>>> and dot
>>>>>>>>> > notations for access, as disadvantages, and I'm not aware of any
>>>>>>>>> advantages.
>>>>>>>>> > If there aren't any that compensate for the disadvantages, then
>>>>>>>>> it's a net
>>>>>>>>> > negative
>>>>>>>>>
>>>>>>>>> @Naveen — a handful of things. Objects are indeed a perfectly
>>>>>>>>> reasonable choice
>>>>>>>>> for modeling kvp collections a lot of the time. On the other hand,
>>>>>>>>> because
>>>>>>>>> objects in ES serve double duty as ways to model data and ways to
>>>>>>>>> "model code",
>>>>>>>>> they are not always ideal for the former case on account of the
>>>>>>>>> features that
>>>>>>>>> exist mainly to serve the second. Some examples of things that
>>>>>>>>> make maps useful:
>>>>>>>>> inherently iterable; no prototype chain access lookup; no
>>>>>>>>> collision with
>>>>>>>>> `Object.prototype` property name when hashing by arbitrary keys;
>>>>>>>>> potentially
>>>>>>>>> more efficient for situations where keys are frequently removed;
>>>>>>>>> `map.has()` is
>>>>>>>>> more straightforward than having to consider whether you want `key
>>>>>>>>> in` or
>>>>>>>>> `Object.hasOwnProperty` or which properties have been defined as
>>>>>>>>> enumerable or
>>>>>>>>> not; iteration order of entries is 1:1 with insertion order; and
>>>>>>>>> of course, keys
>>>>>>>>> can be of any type. Further, maps can be subclassed to constrain
>>>>>>>>> the types that
>>>>>>>>> they may hold or add other behaviors without needing to define
>>>>>>>>> custom Proxies.
>>>>>>>>>
>>>>>>>>> Some general use cases: registries; hashing data where keys are
>>>>>>>>> from external
>>>>>>>>> input; kvp collections which are ordered; kvp collections which
>>>>>>>>> will be subject
>>>>>>>>> to later transformations; kvp collections to which new keys are
>>>>>>>>> frequently added
>>>>>>>>> or removed.
>>>>>>>>>
>>>>>>>>> While I hope that information is somewhat helpful, there are
>>>>>>>>> probably much more
>>>>>>>>> detailed resources online (including, I suspect, past discussions
>>>>>>>>> on this list)
>>>>>>>>> which could explain some of those things better or which include
>>>>>>>>> cases I haven’t
>>>>>>>>> thought of.
>>>>>>>>> _______________________________________________
>>>>>>>>> es-discuss mailing list
>>>>>>>>> es-discuss at mozilla.org
>>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>>
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> es-discuss mailing list
>>>>>>>> es-discuss at mozilla.org
>>>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>> _______________________________________________
>>>>>> es-discuss mailing list
>>>>>> es-discuss at mozilla.org
>>>>>> https://mail.mozilla.org/listinfo/es-discuss
>>>>>>
>>>>>>
>>>>>
>>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20170814/31a4dac2/attachment-0001.html>


More information about the es-discuss mailing list