I have a modal for adding new contacts, in order to disable the save button if no data has entered I check if the contact object is empty, is there a shorter way to check for an empty complex object?
let isContactEmpty = true
Object.keys(contact).forEach(field => {
if (typeof contact[field] === 'string' && contact[field]) {
isContactEmpty = false
return
}
if (typeof contact[field] === 'object') {
contact[field].forEach(fieldVal => {
if (fieldVal.value.length) {
isContactEmpty = false
}
})
}
})
1 Answer 1
- Is there a particular reason you're using a
.forEach()
instead offor-of
?. Because.forEach()
uses a function for iteration, you don't have a way to stop early once you've you know the contact is not empty. If you usedfor-of
instead, you can justreturn false
once you know the result will be false. - It looks like you're doing a
typeof value === 'object'
to check if something is an array. Instead, you can doArray.isArray(value)
. - You're looping over the keys of the object, but you only use the key to get the field's value. Why not just loop over the values instead with
Object.values()
?
With these suggestions applied, your code would look something like this:
function isContactEmpty(contact) {
for (const field of Object.values(contact)) {
if (typeof field === 'string' && field) {
return false
} else if (Array.isArray(field)) {
for (const { value } of field) {
if (value.length) return false
}
}
}
return true
}
But, we can take it a step further. Javascript has a higher-level function to do exactly what we're doing with these loops, but without the boilerplate - array.every()
. It takes a callback that returns a boolean and gets called with each element of an array. The return value of every() is true if all the callbacks returned true, or false if one of them returned false. (It'll also stop iterating as soon as one callback returns false).
const isContactEmpty = contact => (
Object.values(contact).every(field => {
if (typeof field === 'string') return !field
if (Array.isArray(field)) return areArrayEntriesEmpty(field)
return true
})
)
const areArrayEntriesEmpty = field => (
field.every(({ value }) => value.length === 0)
)
-
\$\begingroup\$ Since your implementation iterate over
Object.values()
. Maybefield
is not a good name for loop variable. \$\endgroup\$tsh– tsh2021年02月07日 03:56:52 +00:00Commented Feb 7, 2021 at 3:56
contact
variable and what is considered as an empty object? \$\endgroup\$