1
\$\begingroup\$

I have a getter in my vuex module which gets data from a nested object, then check if there is any key match to the string and push these matched objects into an array. ESLint says that for..in loops iterate over the entire prototype chain, which is virtually never what I want. Its suggests to use Object.{keys,values,entries}, and iterate over the resulting array. How can I refactor this?

getUsersData({ users: { data: { users } } }) {
  if (users) {
    const arr = Object.keys(users.stats || {}).map(key => users.stats[key]);
    const str = 'active';
    const newArr = [];
    arr.forEach((el) => {
      const obj = {};
      for (const key in el) {
        if (!key.includes(str)) {
          obj[key] = el[key];
        }
      }
      newArr.push(obj);
    });
    return newArr;
  }
  return [];
}
\$\endgroup\$
1
\$\begingroup\$

Your original question has a partial answer here I believe. In fact, ESLint is telling you the exact method(s) to use, which is Object.keys(el), for example.


Aside from that, there are a few semi-related things you can refactor...

  • Object.keys(users.stats || {}).map(key => users.stats[key]) is essentially the same as Object.values(users.stats || {}).

...as well as unrelated ones:

  • Names like arr, el, newArr, obj, key, and str are extremely abstract, and dealing with them in real code forces spending brain cycles on decrypting their meaning instead of understanding the intent of the code. In fact, I would hesitate to post a question before renaming the variable into something meaningful. See, the readers don't know the complete structure of the object(s) you're working with and it complicates the review process.
  • Unnecessary temporary objects may be avoided, if map(), filter(), reduce() and other chaining-friendly functions are used together.
  • A guarding construction if (!users) return [] is more idiomatic for JavaScript/TypeScript and reduces the nesting (fewer {s and }s).

The result may look something like this. I'm sorry if I missed something — I don't know how to reliably test that my refactoring went well. Plus, it's a late night in my timezone now, so my brain acts funny. :)

getUsersData({ users: { data: { users } } }) {
  if (!users) return [];

  return Object.values(users.stats || {})
    .map((statValues) => {
      Object
        .getOwnPropertyNames(statValues)
        .filter(key => !key.includes('active'))
        .reduce((result, key) => {
          result[key] = statValues[key];
          return result;
        }, {});
    });
}
\$\endgroup\$
  • \$\begingroup\$ Thank you! Definitely, you gave me very good advise. I changed my code and it still works. :) \$\endgroup\$ – Olga B May 23 '18 at 11:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.