noEagerArrayMethodsInLoops (JavaScript)
Summary
Section titled “Summary”- Rule available since:
v2.6.3 - Diagnostic Category:
lint/nursery/noEagerArrayMethodsInLoops - This rule doesn’t have a fix.
- The default severity of this rule is warning.
- Sources:
- Same as
unicorn/no-duplicate-loops
- Same as
How to configure
Section titled “How to configure”{ "linter": { "rules": { "nursery": { "noEagerArrayMethodsInLoops": "error" } } }}Description
Section titled “Description”Disallow .map() and .filter() calls in the header of for...of loops.
Calling .map() or .filter() on an array in the header of a for...of or
for await...of loop goes through the items twice.
The method visits every item to build a new array, and then the loop visits every item of that new array.
Doing the same work inside the loop body avoids the extra array and the second pass.
The rule only checks calls written directly in the loop header. It doesn’t report an array that is stored in a variable before the loop.
The rule ignores calls on iterators. An iterator is an object that produces its values one at a time,
so its .map() and .filter() methods don’t build an array.
The rule treats the following as iterators:
- The result of
.values(),.keys(), or.entries()called without arguments, or of.matchAll(). - The result of
Iterator.from(),Iterator.concat(),Iterator.zip(), orIterator.zipKeyed(). - The result of calling
.map(),.filter(),.flatMap(),.take(), or.drop()on an iterator. - The result of calling a generator function declared in the same file.
- A
constvariable that is assigned one of the values above. - In TypeScript, a value whose type annotation or type assertion names a built-in iterator type,
such as
Iterator<string>orGenerator<number>, or a type alias for one. This includes the result of calling a function declared in the same file with such a return type.
Examples
Section titled “Examples”Invalid
Section titled “Invalid”for (const name of users.map((user) => user.name)) { console.log(name);}code-block.js:1:20 lint/nursery/noEagerArrayMethodsInLoops ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ This .map() call builds a new array that is only used by the for...of loop.
> 1 │ for (const name of users.map((user) => user.name)) {
│ ^^^^^^^^^
2 │ console.log(name);
3 │ }
ℹ .map() visits every item to build the array before the loop starts, and the loop then visits every item again. The array is discarded after the loop.
ℹ Loop over the original items and do the callback's work inside the loop body.
ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.
for (const user of users.filter((user) => user.isActive)) { console.log(user);}code-block.js:1:20 lint/nursery/noEagerArrayMethodsInLoops ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
⚠ This .filter() call builds a new array that is only used by the for...of loop.
> 1 │ for (const user of users.filter((user) => user.isActive)) {
│ ^^^^^^^^^^^^
2 │ console.log(user);
3 │ }
ℹ .filter() visits every item to build the array before the loop starts, and the loop then visits every item again. The array is discarded after the loop.
ℹ Loop over the original items and skip the unwanted ones inside the loop body, for example with an if statement.
ℹ This rule belongs to the nursery group, which means it is not yet stable and may change in the future. Visit https://biomejs.dev/linter/#nursery for more information.
for (const user of users) { console.log(user.name);}
for (const user of users) { if (user.isActive) { console.log(user); }}
// `.values()` returns an iterator, so `.map()` doesn't build an array.for (const name of users.values().map((user) => user.name)) { console.log(name);}
// The array is created before the loop.const names = users.map((user) => user.name);for (const name of names) { console.log(name);}Related links
Section titled “Related links”Copyright (c) 2023-present Biome Developers and Contributors.