Iterators and Generators

  • 11.1 Don’t use iterators. Prefer JavaScript’s higher-order functions instead of loops like for-in or for-of. eslint: no-iterator no-restricted-syntax

    Why? This enforces our immutable rule. Dealing with pure functions that return values is easier to reason about than side effects.

    Use map() / every() / filter() / find() / findIndex() / reduce() / some() / … to iterate over arrays, and Object.keys() / Object.values() / Object.entries() to produce arrays so you can iterate over objects.

    1. const numbers = [1, 2, 3, 4, 5];
    2. // bad
    3. let sum = 0;
    4. for (let num of numbers) {
    5. sum += num;
    6. }
    7. sum === 15;
    8. // good
    9. let sum = 0;
    10. numbers.forEach((num) => {
    11. sum += num;
    12. });
    13. sum === 15;
    14. // best (use the functional force)
    15. const sum = numbers.reduce((total, num) => total + num, 0);
    16. sum === 15;
    17. // bad
    18. const increasedByOne = [];
    19. for (let i = 0; i < numbers.length; i++) {
    20. increasedByOne.push(numbers[i] + 1);
    21. }
    22. // good
    23. const increasedByOne = [];
    24. numbers.forEach((num) => {
    25. increasedByOne.push(num + 1);
    26. });
    27. // best (keeping it functional)
    28. const increasedByOne = numbers.map(num => num + 1);

  • 11.2 Don’t use generators for now.

    Why? They don’t transpile well to ES5.

  • 11.3 If you must use generators, or if you disregard our advice, make sure their function signature is spaced properly. eslint: generator-star-spacing

    Why? function and * are part of the same conceptual keyword - * is not a modifier for function, function* is a unique construct, different from function.

    1. // bad
    2. function * foo() {
    3. // ...
    4. }
    5. // bad
    6. const bar = function * () {
    7. // ...
    8. };
    9. // bad
    10. const baz = function *() {
    11. // ...
    12. };
    13. // bad
    14. const quux = function*() {
    15. // ...
    16. };
    17. // bad
    18. function*foo() {
    19. // ...
    20. }
    21. // bad
    22. function *foo() {
    23. // ...
    24. }
    25. // very bad
    26. function
    27. *
    28. foo() {
    29. // ...
    30. }
    31. // very bad
    32. const wat = function
    33. *
    34. () {
    35. // ...
    36. };
    37. // good
    38. function* foo() {
    39. // ...
    40. }
    41. // good
    42. const foo = function* () {
    43. // ...
    44. };