London | 26-ITP-Jan | Carlos Abreu |Sprint 2 | Data Module Groups - #1139
London | 26-ITP-Jan | Carlos Abreu |Sprint 2 | Data Module Groups#1139carlosyabreu wants to merge 5 commits into
Conversation
| const counts = {}; | ||
|
|
||
| // Iterate through each item in the array | ||
| for (let i = 0; i < items.length; i++) { | ||
| const item = items[i]; | ||
|
|
||
| // If the item already exists in counts, increment it | ||
| // Otherwise, initialize it to 1 | ||
| if (counts[item]) { | ||
| counts[item]++; | ||
| } else { | ||
| counts[item] = 1; | ||
| } | ||
| } |
There was a problem hiding this comment.
Does the following function call return the value you expect?
tally(["toString", "toString"]);
Suggestion:
- Look up an approach to create an empty object with no inherited properties.
- Use
Object.hasOwn(). - Use Map object.
There was a problem hiding this comment.
Thanks for your wise input.
It made me to rethink completely the implementation.
Going to the point.
Looking at this code, the function call tally(["toString", "toString"]) will not return the expected result of
{ "toString": 2 }. The issue is with the object property access and JavaScript's prototype chain. When the code checks if (counts[item]), it's not just checking if the object has that own property, it's checking if the value at that key is truthy.
However, for the string "toString", when counts["toString"] is accessed, JavaScript looks up the prototype chain and finds Object.prototype.toString (a function). Since functions are truthy, the condition if (counts[item]) evaluates to true even though counts doesn't have its own "toString" property.
This causes the code to try to increment counts["toString"]++, which is problematic because:
- It's not possible to increment a function
- This would set counts["toString"] to NaN
Using the modern approach of Object.hasOwn() implementation:
function tally(items) {
if (!Array.isArray(items)) {
throw new Error("Input must be array");
}
const counts = Object.create(null); // Empty object with no prototype
for (let i = 0; i < items.length; i++) {
const item = items[i];
if (Object.hasOwn(counts, item)) {
counts[item]++;
} else {
counts[item] = 1;
}
}
return counts;
}
Object.hasOwn() properly checks for own properties rather than looking up the prototype chain.
|
Changes look good. Well done. |
|
Closing PR because the January ITP run has finished. Feel free to re-open if you're still working on it. |
Learners, PR Template
Self checklist
Changelist
PR for Sprint 2 Data Group Module