1
\$\begingroup\$

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
 }
 })
 }
 })
asked Feb 3, 2021 at 7:06
\$\endgroup\$
2
  • \$\begingroup\$ The current question title, which states your concerns about the code, applies to too many questions on this site to be useful. The site standard is for the title to simply state the task accomplished by the code. Please see How do I ask a good question?. \$\endgroup\$ Commented Feb 3, 2021 at 9:28
  • 1
    \$\begingroup\$ Can you please add some possible values for contact variable and what is considered as an empty object? \$\endgroup\$ Commented Feb 4, 2021 at 12:16

1 Answer 1

2
\$\begingroup\$
  • Is there a particular reason you're using a .forEach() instead of for-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 used for-of instead, you can just return 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 do Array.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)
)
Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges202 bronze badges
answered Feb 4, 2021 at 3:38
\$\endgroup\$
1
  • \$\begingroup\$ Since your implementation iterate over Object.values(). Maybe field is not a good name for loop variable. \$\endgroup\$ Commented Feb 7, 2021 at 3:56

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.