30-seconds-of-code: objectToPairs

Created on 6 Apr 2019  路  20Comments  路  Source: 30-seconds/30-seconds-of-code

https://github.com/30-seconds/30-seconds-of-code/blob/master/snippets/objectToPairs.md
saw this one today.
There is a native way of doing the same thing via Object.entries.

discussion not-stale opinions needed question

All 20 comments

This predates the Object.entries method. It might be a good idea to note that Object.entries exists and shunt this to an Object.entries call and deprecate it

Object.entries support is just below 90%. Can we discuss this in a month or so when it's past 90%? It's my OCD talking, but it's not such a bad idea to wait for just a bit.

Two minor concerns of mine are as follows:

  1. We shouldn't remove the method. Even if it works as an alias for the native method, it's not going anywhere as far as I am concerned, as this would break compatibility and we don't want that. Plus, Object.entries has an obscure, forgettable name. Let's help make it discoverable.
  2. The original snippet should be renamed when we transition and moved to the archive. It's interesting if someone wants to see how they could go about implementing it. After all, we are a learning resource and a package, let's take both of these things into account.

What did you mean by Object.entries having an obscure, forgettable name? Also, what can be done to raise Object.entries support to above 90%?

@Chalarangelo the 10% that doesn't support it is literally IE11. Considering it is not only no longer actively developed we should probably not include it in this calculation. We could probably safely use it since anyone still supporting IE11 will be using a transpiler for safety or they miss out on too many features to be productive.

@himdiv23 convince people to drop IE11 for a modern and supported browser?

Also Object.entries is an obscure name as an entry is usually defined as a keyed index... or... basically an Object in JS as the most basic data type. As such it would probably be better known as Object.toPairs, but since we didn't get to make that choice...

Also is there any reason we call it objectToPairs instead of just toPairs? toPairs could be adapted to also support other data types.

@skatcat31 yeah it's mainly IE. We could theoretically wait until the release of the next Windows version that includes the release of a stand-alone Edge that people might swap with their older IEs in Windows 7, right?

It's objectToPairs because it's focused on objects and it's easy to find like that. Actually, renaming will break compatibility and it's also one of the most popular terms for finding us, so maybe just develop other xToPairs methods in the codebase as well? Food for thought.

Might be good food for thought. Either that or a general toPairs method that handles the most common cases(Objects, Sets, Maps)?

@skatcat31 The argument against a general toPairs method is probably testing and compatibility both now and in the long run. I'd still go with objectToPairs, setToPairs etc, but a general version would work if everyone agrees on that one.

@fejes713 @flxwu @atomiks Your opinions?

Code thoughts on a generic toPairs() for any iterator falling back to Object

new Set([[1,2],[3,4]])
Set(2) {Array(2), Array(2)}

Array.from((new Set([[1,2],[3,4]])).entries())
(2) [Array(2), Array(2)]

Array.from((new Map([[1,2],[3,4]])).entries())
(2) [Array(2), Array(2)]
0: (2) [1, 2]
1: (2) [3, 4]
length: 2
__proto__: Array(0)

Array.from([1,2,3].entries())
(3) [Array(2), Array(2), Array(2)]
0: (2) [0, 1]
1: (2) [1, 2]
2: (2) [2, 3]
length: 3
__proto__: Array(0)

new Set()[Symbol.iterator]
茠 values() { [native code] }

new Map()[Symbol.iterator]
茠 values() { [native code] }

[][Symbol.iterator]
茠 values() { [native code] }

const toPairs = o => o[Symbol.iterator] instanceof Function && o.entries instanceof Function ? Array.from(o.entries()) : Object.entries(o)

any object should work due to conversion to a basic key pairing, so it should have 1 of 2 outcomes:

  • an Array(more than likely empty if you don't know what you're doing)
  • throws a typeError(undefined, null)

Works with:

  • Objects: [[k,v],...]
  • Strings: [[i,v],...]
  • Numbers: []
  • Booleans: []
  • Iterables: [[k,v],...]
  • Symbols: []

I was only able to throw on undefined and null, but if you're passing undefined or null to a unary function you should know exactly what you're doing

What if we actually keep objectToPairs as the beginner snippet using Object.entries() and toPairs as an advanced function that works for everything? Best of both worlds in my opinion.

... that was my suggestion? I must have left it a little too ambiguous

I know I'm forgetting some basic types above, but it should be simple enough

I think we should move forward with this suggestion soon, then. It looks quite promising and it's probably the first snippet that dares delve into iterator territory like that.

I'll work on that when I have some time, but if anyone gets ot it first I won't be too sad. I'm going to be taking it easy tonight though... work has had some rather complex buisiness logic come up recently that I've been working on so I need a night of video games to relax

Set has a weird behavior where if you apply a Array.from (or just spread it) on a Set you'll get tuples of [value, value] instead of [key, value]. To get the correct [key, value] tuples you need to apply a second Array.from.

Anyone knows why that is? This would also make it hard to create a simple generic method to transform anything into pairs.

[...(new Set([3,'a',null])).entries()] // [[3, 3], ["a", "a"], [null, null]]
[...([...new Set([3,'a',null])]).entries()] // [[0, 3], [1, "a"], [2, null]]

@vmarchesin it's because to a set, a key IS it's identifier and value. Set is an associate iterable where the value is keyed by itself and it has constant time lookup. This is useful for large collections where you need to quickly and consistently look for existence in the Set. Array.from() is thus working as expected since the value is it's key. I don't know if always returning the same order as initial input is guaranteed of the top of my head. What you've found however is the order the values from the set were put into the Array.

Object.entries() support is 92% as of now. Let's move forward with this when we have the time.

IE11 seems to be roughly 1/3 or so of the users... the rest are other users locked on older browsers (which seems wild since they largely self-update), unsure of the source of caniuse metrics though. It's around 92% supported now. All the same, I'd probably favor Object.entries and reference the MDN Polyfill[0].

[0] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Polyfill

You are welcome to submit a PR updating the snippet to use the native method, as it's well-supported. However, we should keep the existing one in the archive (I think having both snippets with the same name should not conflict, but better rename the archived version to something like objectToEntries so that it's a hint that it acts as a polyfill?).

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fejes713 picture fejes713  路  4Comments

YusofBandar picture YusofBandar  路  5Comments

Speuta picture Speuta  路  3Comments

fplgusmao picture fplgusmao  路  4Comments

Chalarangelo picture Chalarangelo  路  5Comments