Originally posted on my blog.
Someone recently asked in a Slack channel how they might clean up the following code:
getNames (contacts) {
let contacts_set = []
contacts.forEach((contact) => {
let firstName = get(contact, 'contactInfo.firstName')
let lastName = get(contact, 'contactInfo.lastName')
let fullName = `${firstName} ${lastName}`
if (contacts_set.includes(fullName)) {
return
} else {
contacts_set.push(fullName)
}
set(this, 'contactsSet', contactsSet)
})
}
(Note that the get
and set
going on here seemed to be Ember-specific, or a _.get
type of thing. I don't know Ember, so I'm not positive.)
And I said, how about this?
getNames: (contacts) =>
[...new Set(
contacts.map(({ contactInfo: { firstName, lastName }}) =>
`${firstName} ${lastName}`))]
I like this version because it's concise, readable (to me, at least?), mutation-free, and declarative.
And then someone else asked:
Can some one eli5 what
Set
is that's referenced above?
Which made me realise that a lot of folks still aren't using a lot of the nice new things from ES2015, so I explained a bit. Here's how I understand it.
Set is a new (in ES2015) iterable builtin (like Array, String, TypedArray). Map is also new in 2015. Set is to Array as Map is to Object, kinda.
For practical usage Set is basically Array but unique, and with different methods. add
, has
, delete
, size
, and some others. There's a lot more info on MDN.
You can pass Set
an iterable, which is why the thing I have above works (because the contacts.map...
thing inside new Set()
results in an array).
In that case Set
isn't being used for too much besides just the fact that it's Set
(so it only holds unique values). Someone else pointed out in the same channel that maybe it's not the best idea if you have a very large collection, because then you're creating a whole extra collection in the process, which is totally true.
There's a bit more background here on what JS's Set
is supposed to be kind of like.
And underneath it sorta looks like this:
class Set {
constructor () {
this.storage = []
}
add (a) {
if (!this.storage.includes(a)) {
this.storage.push(a)
}
}
has (a) {
return this.storage.includes(a)
}
remove (a) {
this.storage.splice(this.storage.indexOf(a), 1)
}
}
That's a lot of stuff, but mostly you can think of Set
as a thing that's like Array
but it only holds unique things.
There's also a WeakSet
which can only hold objects. I haven't really found a valid use case for WeakSet
and WeakMap
yet, personally.
Set
turns out to be pretty useful. Definitely play around with it!
Top comments (0)