Accessing (n)th key from an object

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Accessing (n)th key from an object

somonek
Hi all,

Assuming that 

const myObject = {
  one: 123,
  two: 456,
};

could 
myObject[in 0] === 'one' // true

be a better alternative of  
Object.keys(myObject)[0]

and 
myObject[in 3] === undefined

without the need to convert all the object keys into an array, but directly accessing one.

Best,
Serghei


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

Mike Samuel


On Tue, Apr 24, 2018 at 9:54 AM, somonek <[hidden email]> wrote:
Hi all,

Assuming that 

const myObject = {
  one: 123,
  two: 456,
};

could 
myObject[in 0] === 'one' // true

be a better alternative of  
Object.keys(myObject)[0]

and 
myObject[in 3] === undefined

without the need to convert all the object keys into an array, but directly accessing one.

Why is this something that warrants extra syntax and not an optimization better left to sufficiently smart engines?

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

T.J. Crowder-2
In reply to this post by somonek
On Tue, Apr 24, 2018 at 2:54 PM, somonek
<[hidden email]> wrote:
> ...
>
> could
> myObject[in 0] === 'one' // true

What's the use case? Relying on the order of the properties in the object is almost always a bad idea (although if I read the current spec correctly, `Object.keys` is no longer exempt from order as it once was). The only time I've seen this done that seemed reasonable was when the object was known to have a single own enumerable property but that property's name was unknown (which was, in itself, an X/Y problem -- the real problem was why that name was unknown/varied at runtime).

-- T.J. Crowder

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

somonek
The use case is: 
(long story short)

I have an array of items coming from an api. They're converted to an object having the ids as keys for faster access of single items and loaded to a global store. 
Then in React.js and I want to render only the first 2 items with a "See more" that would render the rest of them. 
It would be handy (and probably more performant when the object is big as in my case) to have:

const product1 = myItems[in 0];
const product2 = myItems[in 1];

instead of converting everything to an array first and then accessing the first items by index.




On Tue, Apr 24, 2018 at 4:18 PM, T.J. Crowder <[hidden email]> wrote:
On Tue, Apr 24, 2018 at 2:54 PM, somonek
<[hidden email]> wrote:
> ...
>
> could
> myObject[in 0] === 'one' // true

What's the use case? Relying on the order of the properties in the object is almost always a bad idea (although if I read the current spec correctly, `Object.keys` is no longer exempt from order as it once was). The only time I've seen this done that seemed reasonable was when the object was known to have a single own enumerable property but that property's name was unknown (which was, in itself, an X/Y problem -- the real problem was why that name was unknown/varied at runtime).

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

David Rajchenbach-Teller-2
Doing this sounds pretty fragile. Do you have any guarantee that the
order of fields is the same as the order of the array? Even if that's
the case in your scenario, it's pretty uncommon.

On 24/04/2018 16:41, somonek wrote:

> The use case is: 
> (long story short)
>
> I have an array of items coming from an api. They're converted to an
> object having the ids as keys for faster access of single items and
> loaded to a global store. 
> Then in React.js and I want to render only the first 2 items with a "See
> more" that would render the rest of them. 
> It would be handy (and probably more performant when the object is big
> as in my case) to have:
>
> const product1 = myItems[in 0];
> const product2 = myItems[in 1];
>
> instead of converting everything to an array first and then accessing
> the first items by index.
>
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

T.J. Crowder-2
In reply to this post by somonek
In that use case, I'd just remember those two objects from when you
converted the array to an object, e.g.:

```js
const obj = Object.create(null);
for (const item of theArray) {
    obj[item.key] = item;
}
const firstItems = theArray.slice(0, 2);
```

...then use `firstItems` for showing the first two. Also has the
advantage that you can easily change how many you show before the "See
more."

-- T.J. Crowder

On Tue, Apr 24, 2018 at 3:41 PM, somonek <[hidden email]> wrote:

> The use case is:
> (long story short)
>
> I have an array of items coming from an api. They're converted to an object
> having the ids as keys for faster access of single items and loaded to a
> global store.
> Then in React.js and I want to render only the first 2 items with a "See
> more" that would render the rest of them.
> It would be handy (and probably more performant when the object is big as in
> my case) to have:
>
> const product1 = myItems[in 0];
> const product2 = myItems[in 1];
>
> instead of converting everything to an array first and then accessing the
> first items by index.
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

T.J. Crowder-2
In reply to this post by David Rajchenbach-Teller-2
On Tue, Apr 24, 2018 at 4:06 PM, David Teller
<[hidden email]> wrote:
>
> Doing this sounds pretty fragile. Do you have any guarantee that the
> order of fields is the same as the order of the array? Even if that's
> the case in your scenario, it's pretty uncommon.

If we make a couple of assumptions:

1. He's adding the properties to a newly-created object in array order
2. None of the keys is an [integer index][1]

...then yes, the order is guaranteed (even for `Object.keys`, nowadays
-- that wasn't true in ES2015, not sure when it changed and the ECMA
site is down so I can't check the 2016 or 2017 snapshots [note to
self: keep local copies!]).

Agreed it's not the best way to go about it, though. :-)

-- T.J. Crowder

[1]: https://tc39.github.io/ecma262/#sec-object-type
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

Michael Rosefield
In reply to this post by T.J. Crowder-2
I've found myself using that pattern, actually. Say you have multiple variables and want to pass one of them on to a function, which wants to know the value (of course) of that variable but also some kind of name to know which one was passed on.

The easiest way to do this in one pass at the stage you pass it on is for the variable name to match the one needed later, and send it to the function as the object `{ whateverName }`.

It does require, alas, more fiddling about to get the key/value pair from the object after.

On Tue, 24 Apr 2018 at 15:19 T.J. Crowder <[hidden email]> wrote:
On Tue, Apr 24, 2018 at 2:54 PM, somonek
<[hidden email]> wrote:
> ...
>
> could
> myObject[in 0] === 'one' // true

What's the use case? Relying on the order of the properties in the object is almost always a bad idea (although if I read the current spec correctly, `Object.keys` is no longer exempt from order as it once was). The only time I've seen this done that seemed reasonable was when the object was known to have a single own enumerable property but that property's name was unknown (which was, in itself, an X/Y problem -- the real problem was why that name was unknown/varied at runtime).

-- T.J. Crowder
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

T.J. Crowder-2
On Tue, Apr 24, 2018 at 4:24 PM, Michael Luder-Rosefield
<[hidden email]> wrote:
> I've found myself using that pattern, actually. Say you have multiple
> variables and want to pass one of them on to a function, which wants to know
> the value (of course) of that variable but also some kind of name to know
> which one was passed on.
>
> The easiest way to do this in one pass at the stage you pass it on is for
> the variable name to match the one needed later, and send it to the function
> as the object `{ whateverName }`.

On those rare occasions, the way I'd use would be `["whateverName",
whateverName]` (granted it's more verbose at the call site). That's
what `Object.entries` and `Map.prototype.entries` do, for instance,
and it's friendly to destructuring:

```js
function example([name, value]) {
    console.log(`${name} = ${value}`);
}
example(["answer", 42]);
```

-- T.J. Crowder
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

Augusto Moura
In reply to this post by somonek
Assuming `Object.keys` has the same order as a simple `for..in` (as stated in mdn)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys], we can already implement a function to build a iterator from object keys, and then we can destruct or use others helpers to minimize the array creation. Something like:

``` js
function* keysIterator(obj) {
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      yield key;
    }
  }
}
const obj = { foo: 12, bar: 89 };

// Using destructuring
const [firstProp, secondProp, ...othersKeys] = keysIterator(obj);

// Using some helper functions
const props = take(2, 10)(obj);
```

The discussion IMHO is if we need that as a built in helper (maybe `Object.keysIterator()`), and if we need to extend it to `Object.values` and `Object.entries`.

Em ter, 24 de abr de 2018 às 10:54, somonek <[hidden email]> escreveu:
Hi all,

Assuming that 

const myObject = {
  one: 123,
  two: 456,
};

could 
myObject[in 0] === 'one' // true

be a better alternative of  
Object.keys(myObject)[0]

and 
myObject[in 3] === undefined

without the need to convert all the object keys into an array, but directly accessing one.

Best,
Serghei

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
--
Augusto Moura

_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

T.J. Crowder-2
On Tue, Apr 24, 2018 at 5:58 PM, Augusto Moura <[hidden email]> wrote:
> Assuming `Object.keys` has the same order as a simple `for..in` (as stated
> in
> mdn)[<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys].">https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys]...

We'll have to fix that page, the spec does not define the order in which `for-in` will enumerate property names. (It does define the order in which `Object.keys` will provide the property names, now, but not `for-in`.) That said, all modern and modern-ish implementations I've tested (to be fair, just V8, SpiderMonkey, Chakra, and IE11's JScript) do indeed follow the defined order with `for-in` as well, with an object's own properties coming before inherited ones - http://jsfiddle.net/arhbn3k2/1/ (IE11-friendly version without Symbols: http://jsfiddle.net/arhbn3k2/5/). (Provided I haven't screwed up that test.) But it's specifically *not* specified - from [EnumerateObjectProperties][1] (the op `for-in` uses to initialize its loop):

> The mechanics **and order** of enumerating the properties **is not specified** but must conform to the rules specified below.

*(my emphasis)* It says it has to use [[OwnPropertyKeys]] to get the own property keys at each level, but doesn't -- as far as I can tell -- define the sequence of own vs. inherited properties.

`Object.entries` follows the order (own properties only):

```js
const [first, second, ...rest] = Object.entries(obj);
```

...but I don't think that, or `keysIterator`, really helps somonek vs. what he's doing now (`Object.keys`).

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

Jordan Harband
Regardless of what's in the spec, relying on objects having an order among their properties violates the conceptual mental model of objects: a bag of unordered key/value pairs.

If you want to convert an array - the best way to preserve order - into an object for "performance" reasons, then you may also want to preserve an array of IDs so that ordering can be relied upon.

On Tue, Apr 24, 2018 at 10:26 AM, T.J. Crowder <[hidden email]> wrote:
On Tue, Apr 24, 2018 at 5:58 PM, Augusto Moura <[hidden email]> wrote:
> Assuming `Object.keys` has the same order as a simple `for..in` (as stated
> in

We'll have to fix that page, the spec does not define the order in which `for-in` will enumerate property names. (It does define the order in which `Object.keys` will provide the property names, now, but not `for-in`.) That said, all modern and modern-ish implementations I've tested (to be fair, just V8, SpiderMonkey, Chakra, and IE11's JScript) do indeed follow the defined order with `for-in` as well, with an object's own properties coming before inherited ones - http://jsfiddle.net/arhbn3k2/1/ (IE11-friendly version without Symbols: http://jsfiddle.net/arhbn3k2/5/). (Provided I haven't screwed up that test.) But it's specifically *not* specified - from [EnumerateObjectProperties][1] (the op `for-in` uses to initialize its loop):

> The mechanics **and order** of enumerating the properties **is not specified** but must conform to the rules specified below.

*(my emphasis)* It says it has to use [[OwnPropertyKeys]] to get the own property keys at each level, but doesn't -- as far as I can tell -- define the sequence of own vs. inherited properties.

`Object.entries` follows the order (own properties only):

```js
const [first, second, ...rest] = Object.entries(obj);
```

...but I don't think that, or `keysIterator`, really helps somonek vs. what he's doing now (`Object.keys`).

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

T.J. Crowder-2
On Tue, Apr 24, 2018 at 7:07 PM, Jordan Harband <[hidden email]> wrote:
> Regardless of what's in the spec, relying on objects having an order among
> their properties violates the conceptual mental model of objects: a bag of
> unordered key/value pairs.
>
> If you want to convert an array - the best way to preserve order - into an
> object for "performance" reasons, then you may also want to preserve an
> array of IDs so that ordering can be relied upon.

Absolutely agree. As I said originally, relying on the order of the
properties in the object is almost always a bad idea.

@somonek, an object with an array of keys is probably your best
solution. Wrap it up in an object with an API that all of the code
updating it can use, so you don't have consistency issues. You could
even give it an iterator. :-)

-- T.J. Crowder
_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

somonek
Thanks, hat's probably what I'll do. 

I was also thinking looking at @Augusto's approach that if you replace the object with a Map you can iterate as Augusto mentioned 
const [firstProp, secondProp, ...othersKeys] = myMap;
and the order of items should not be a worry.

Any comments on Map's performance in such a case?

On Tue, Apr 24, 2018 at 8:22 PM, T.J. Crowder <[hidden email]> wrote:
On Tue, Apr 24, 2018 at 7:07 PM, Jordan Harband <[hidden email]> wrote:
> Regardless of what's in the spec, relying on objects having an order among
> their properties violates the conceptual mental model of objects: a bag of
> unordered key/value pairs.
>
> If you want to convert an array - the best way to preserve order - into an
> object for "performance" reasons, then you may also want to preserve an
> array of IDs so that ordering can be relied upon.

Absolutely agree. As I said originally, relying on the order of the
properties in the object is almost always a bad idea.

@somonek, an object with an array of keys is probably your best
solution. Wrap it up in an object with an API that all of the code
updating it can use, so you don't have consistency issues. You could
even give it an iterator. :-)

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss
Reply | Threaded
Open this post in threaded view
|

Re: Accessing (n)th key from an object

Cyril Auburtin

2018-04-24 20:29 GMT+02:00 somonek <[hidden email]>:
Thanks, hat's probably what I'll do. 

I was also thinking looking at @Augusto's approach that if you replace the object with a Map you can iterate as Augusto mentioned 
const [firstProp, secondProp, ...othersKeys] = myMap;
and the order of items should not be a worry.

Any comments on Map's performance in such a case?

On Tue, Apr 24, 2018 at 8:22 PM, T.J. Crowder <[hidden email]> wrote:
On Tue, Apr 24, 2018 at 7:07 PM, Jordan Harband <[hidden email]> wrote:
> Regardless of what's in the spec, relying on objects having an order among
> their properties violates the conceptual mental model of objects: a bag of
> unordered key/value pairs.
>
> If you want to convert an array - the best way to preserve order - into an
> object for "performance" reasons, then you may also want to preserve an
> array of IDs so that ordering can be relied upon.

Absolutely agree. As I said originally, relying on the order of the
properties in the object is almost always a bad idea.

@somonek, an object with an array of keys is probably your best
solution. Wrap it up in an object with an API that all of the code
updating it can use, so you don't have consistency issues. You could
even give it an iterator. :-)

-- T.J. Crowder


_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss



_______________________________________________
es-discuss mailing list
[hidden email]
https://mail.mozilla.org/listinfo/es-discuss