2

The following code expects that all the properties of this.triggeredTests are arrays and calculates their total length:

    let savedLen = 0;

    const values = Object.values(this.triggeredTests);

    for (let i = 0; i < values.length; i += 1) {
      savedLen += values[i].length;
    }

if I try to rewrite this code with for ... in:

    for (const val in values) {
      savedLen += val.length;
    }

I got some annoying errors:

  ✘  http://eslint.org/docs/rules/guard-for-in          The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype
  src\components\entity\Test.vue:171:9
          for (const val in values) {
          ^

  ✘  http://eslint.org/docs/rules/no-restricted-syntax  for..in loops iterate over the entire prototype chain, which is virtually never what you want. Use Object.{keys,values,entries}, and iterate over the resulting array
  src\components\entity\Test.vue:171:9
          for (const val in values) {
          ^


✘ 2 problems (2 errors, 0 warnings)


Errors:
  1  http://eslint.org/docs/rules/no-restricted-syntax
  1  http://eslint.org/docs/rules/guard-for-in

Is it possible to make this for ... in work?

I am to sure what compiler I use, but at least I know that I am working in Node.js v8.12.0 environment with NPM.

EDIT1:

If I use for ... of:

    for (const val of values) {
        savedLen += val.length;
    }

I am getting another error:

    ✘  http://eslint.org/docs/rules/no-restricted-syntax  iterators/generators require regenerator-runtime, which is too heavyweight for this guide to allow them. Separately, loops should be avoided in favor of array iterations
    src\components\entity\Test.vue:171:9
            for (const val of values) {
            ^

EDIT2:

This does not produce errors:

    const values = Object.values(this.triggeredTests);
    const sumCalculator = (accumulator, currentValue) => accumulator + currentValue.length;
    const savedLen = values.reduce(sumCalculator, 0);
Alexey Starinsky
  • 3,699
  • 3
  • 21
  • 57
  • its not a javascript error, its eslint https://eslint.org/docs/rules/guard-for-in – Chris Li Sep 27 '18 at 11:36
  • The errors have a link in them explaining the general issue, including ways to solve it. Have you read them? – Hans Kesting Sep 27 '18 at 11:39
  • 1
    Re your edit: the airbnb linter is opinionated about this stuff and doesn't want you to use `for...of`- see [here](https://github.com/airbnb/javascript/issues/1271). – Kirk Larkin Sep 27 '18 at 11:56
  • It would be `for (const prop in this.triggeredTests) savedLen += this.triggeredTests[prop].length;` if you insisted on `for … in`, but since you are using `Object.values` anyway you don't need any `for … in`. – Bergi Sep 27 '18 at 13:55

4 Answers4

1

I believe you are confusing syntax with python, node is enumerating values of iterable objects using for-of

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

Drahoš Maďar
  • 517
  • 2
  • 6
  • 22
1

Your error are indeed due to eslint and not for loop in javascript. You could probably paste what you have into chrome dev tools and it would work just fine without the compilation.

Specifically these lints

Both of these guard against oddness in for loops related to objects in that it will iterate over all the elements.

In this case if that is a basic array, i would recommend using

values.forEach(iterator)

Austio
  • 5,939
  • 20
  • 34
1

I wouldn't describe the error as annoying here - it's trying to protect you from doing something you don't intend. Take the following example code:

Array.prototype.someFunc = function () { }

const someObject = { a: 'A', b: 'B', c: 'C' };
const someObjectValues = Object.values(someObject);

for (const v in someObjectValues) {
    console.log(v);
}

There are at least two problems here:

  1. v will be the index of the element: instead of A, B and C, you'll get 0, 1 and 2.
  2. You'll also get someFunc, which is clearly not intended.

The simplest solution here is to take note of the linting errors and leave the code as it was.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
  • what is 'x'? did you mean 'v'? – Alexey Starinsky Sep 27 '18 at 13:40
  • Really I am getting '0 1 2 someFunc'. That all is strange... What someFunc does here? – Alexey Starinsky Sep 27 '18 at 13:53
  • By adding a function to the prototype like I have in the example, `someFunc` becomes an [enumerable property](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties), which means it will show up in `for...in` loops like it does here. Adding functions to the prototype allows for extending a type in JavaScript. For example, with the code above, you could call `values.someFunc()` and it would be valid (although it does nothing here as it's an empty function). – Kirk Larkin Sep 27 '18 at 13:55
  • 1
    Figured this out. With 'for...of' I am getting 'A B C'. – Alexey Starinsky Sep 27 '18 at 14:02
1

You are looping through an array. The for...of loop is what you are looking for. If you want to use for...in then try this

 for (const val in values) {
      savedLen += values[val].length;
    }

Also have a look here for some good info on both loops https://bitsofco.de/for-in-vs-for-of/

adam.k
  • 622
  • 3
  • 15