Additional methods for Objects (like Arrays)
Yeah, some languages have this functionality available for maps, e.g.
Erlang erlang.org/doc/man/maps.html#map-2. Might be a good addition,
although considering Map
instead of Object
is worth as well. (although,
when we were discussing of adding Map.prototype.map/filter
, it was
decided that it's better to add them on iterators).
Dmitry
On Fri, Jan 29, 2016 at 3:07 PM, Kaustubh Karkare < kaustubh.karkare at gmail.com> wrote:
I have recently come to feel the need for Object.map, which is like Array.map, except that it receive keys instead of indices.
Object.prototype.map = function(mapFn, context) { return Object.keys(this) .reduce(function(result, key) { result[key] = mapFn.call(context, this[key], key, this); return result; }, {}); };
Also a potential issue of placing it on Object.prototype
is that other
things will inherit it, including unrelated (like strings, regexps,
functions, etc). By this reason seems iterator methods values
, keys
,
and entries
weren't added in ES6 to Object.prototype
.
Dmitry
On Fri, Jan 29, 2016 at 6:08 PM Kaustubh Karkare <kaustubh.karkare at gmail.com>
wrote:
I have recently come to feel the need for Object.map, which is like Array.map, except that it receive keys instead of indices.
Object.prototype.map = function(mapFn, context) { return Object.keys(this) .reduce(function(result, key) { result[key] = mapFn.call(context, this[key], key, this); return result; }, {}); };
Without this, I frequently do the exact same thing as the above manually, which leads to unnecessary code duplication.
Given that, it might make sense to match other methods from Array.prototype
Object.map Object.filter Object.every Object.some Object.reduce Object.find Object.findKey // like Array.findIndex
Are these necessary given the introduction of Object.values() and Object.entries()? tc39/proposal
Are these necessary given the introduction of Object.values() and
Object.entries()?
Object.entries()
works. Object.p.map()
would be shorter to write,
easier to read and more compatible with functions already written for
Array.p.map()
.
On Friday, January 29, 2016, Rick Waldron <waldron.rick at gmail.com> wrote:
On Fri, Jan 29, 2016 at 6:08 PM Kaustubh Karkare < kaustubh.karkare at gmail.com <javascript:_e(%7B%7D,'cvml','kaustubh.karkare at gmail.com');>> wrote:
I have recently come to feel the need for Object.map, which is like Array.map, except that it receive keys instead of indices.
Object.prototype.map = function(mapFn, context) { return Object.keys(this) .reduce(function(result, key) { result[key] = mapFn.call(context, this[key], key, this); return result; }, {}); };
Without this, I frequently do the exact same thing as the above manually, which leads to unnecessary code duplication.
Given that, it might make sense to match other methods from Array.prototype
Object.map Object.filter Object.every Object.some Object.reduce Object.find Object.findKey // like Array.findIndex
Are these necessary given the introduction of Object.values() and Object.entries()? tc39/proposal-object-values-entries
I think what Kaustubh is proposing is that the result is a transformed object/map, not an array. See the reduce method in his implementation.
Dmitry
在 2016/1/30 7:07, Kaustubh Karkare 写道:
I have recently come to feel the need for Object.map, which is like Array.map, except that it receive keys instead of indices.
Object.prototype.map = function(mapFn, context) { return Object.keys(this) .reduce(function(result, key) { result[key] = mapFn.call(context, this[key], key, this); return result; }, {}); };
Without this, I frequently do the exact same thing as the above manually, which leads to unnecessary code duplication.
Given that, it might make sense to match other methods from Array.prototype
Object.map Object.filter Object.every Object.some Object.reduce Object.find Object.findKey // like Array.findIndex
Note that wherever applicable, the ordering is non-deterministic.
I'd rather add them as static methods of Object, e.g.
var result = Object.map(obj, function(value, key) { ... });
Because when I use an object as a map, I usually create it without prototype (Object.create(null)), to avoid unintentional access of properties on Object.prototype.
Not all objects are used as maps, and when using with map we often use Object.create(null)
, so adding to prototype is definitely a bad idea. As for whether we should make them static methods of Object, I personally don't think this is very useful. Using a for-in loop is enough in my opinion.
From: kaustubh.karkare at gmail.com Date: Fri, 29 Jan 2016 18:07:30 -0500 Subject: Additional methods for Objects (like Arrays) To: es-discuss at mozilla.org
I have recently come to feel the need for Object.map, which is like Array.map, except that it receive keys instead of indices. Object.prototype.map = function(mapFn, context) { return Object.keys(this) .reduce(function(result, key) { result[key] = mapFn.call(context, this[key], key, this); return result; }, {});}; Without this, I frequently do the exact same thing as the above manually,which leads to unnecessary code duplication. Given that, it might make sense to match other methods from Array.prototype Object.mapObject.filterObject.everyObject.someObject.reduceObject.findObject.findKey // like Array.findIndex Note that wherever applicable, the ordering is non-deterministic.
Not all objects are used as maps, and when using with map we often use
Object.create(null)
, so adding to prototype is definitely a bad idea.
- Much like we're forced to invoke the prototype directly like (in functions & NodeLists)
Array.prototype.slice.call(arguments)
, an argument could be made that one should need invokeObject.prototype.map.call(objWithoutPrototype, mapFn)
. - My main issue with static methods on the object is the lack of consistency with the array format. But given that we already have
Object.keys
andObject.values
, there's already precedent for this (plus the argument about breaking legacy frameworks). Note that this methods should be on theMap.prototype
at least (givenMap.prototype.keys/values
exist), since this argument doesn't apply in that case.
As for whether we should make them static methods of Object, I personally don't think this is very useful. Using a for-in loop is enough in my opinion.
For-in loops result in unnecessary verbosity, specially in codebases that optimize for readability. Comparing something like:
const normalizedGrey = colors
.map(c => (c.red + c.green + c.blue) / 3)
.filter(g => g < someThreshold)
.map(g => (g - min) / (max - min));
vs
let normalizedGrey = {};
for (var color in colors) {
let c = colors[color];
let g = (c.red + c.green + c.blue) / 3;
if (g < someThreshold) {
normalizedGrey[color] = (g - min) / (max - min);
}
}
The latter has more lines/bytes and is harder to read.
The this-bind operator
would remove the need for officially adding methods to Object.protoype
,
wouldn't it? For example:
import { map, filter } from 'external-lib/objects'
const normalizedGrey = colors
::map(c => (c.red + c.green + c.blue) / 3)
::filter(g => g < someThreshold)
::map(g => (g - min) / (max - min));
Although Rick makes a good point that Object.values and Object.entries make creating functionality similar to that describe by Kaustubh, they are no exactly direct. We have added the requested functions to V2.0 of JavaScript Object Extensions at anywhichway/joex.
I think that these methods should exist in iterator prototypes, with the
native iterators subclassing something like Iterator. Object.entries and
Object.values should return iterators that inherit these methods. Such
wrapper libraries are already coming out, and making existing arrays lazily
iterate already exists in Symbol.iterator
.
Object.entries and Object.values must remain consistent with Object.keys and will return arrays - luckily those are iterable too.
Ok. Never mind. I forgot about that part (I hadn't looked it up lately...) :)
I have recently come to feel the need for
Object.map
, which is likeArray.map
, except that it receive keys instead of indices.Without this, I frequently do the exact same thing as the above manually, which leads to unnecessary code duplication.
Given that, it might make sense to match other methods from
Array.prototype
Note that wherever applicable, the ordering is non-deterministic.