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 [];
}
1 Answer 1
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 asObject.values(users.stats || {})
.
...as well as unrelated ones:
- Names like
arr
,el
,newArr
,obj
,key
, andstr
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;
}, {});
});
}
-
\$\begingroup\$ Thank you! Definitely, you gave me very good advise. I changed my code and it still works. :) \$\endgroup\$Olga B– Olga B2018年05月23日 11:01:46 +00:00Commented May 23, 2018 at 11:01