0

My question looks at the following code,

const arr = ['0', '1', '7', '18', '10', '19', '15'];
const my_obj = {
[Symbol.iterator]: function*() {
for(let index of arr) {
  yield `${index}`;
  }
 }
};
const all = [...my_obj]
.map(i => parseInt(i, 8))

The output is,

(

0,

1,

7,

1,

8,

1,

13

)

When arr is changed to arr = ['0', '1', '24', '26', '28', '29', '17'];

The output is,

(

0,

1,

20,

22,

2,

2,

15

)

Now, I notice a pattern, and I can't explain why,

for 0, 1, and 7, the output is just 0, 1, 7. For 10, 15 and 17, the output is 8, 13 and 15 (a difference of 2). For 18 and 19, the output is 1. For 24 and 26, the output is 20 and 22 (a difference of 4), and for 28 and 29, the output is 2. So, for digit's between 10-20, there's a difference of 2, and for digit's 20-30, there's a difference of 4 (went up by 2). Also, for digit's between 10-20 with digit's 18 and 19, the value is 1, but for digit's between 20-30 with digit's 28 and 29, the value is 2 (increased by 1).

I'm having trouble why this is happening. Could someone please clearly present the reasoning for this functionality?

  • btw, when using `for (let value of array)`, `value` is the value and not an index. – Nina Scholz Dec 29 '19 at 22:46
  • This is nothing to do with generator functions and everything to do with how `parseInt` works. Since you've given it a radix of `8` then the digits `8` and `9` are not valid and will be treated as if you had any other invalid character - e.g., `parseInt("123banana")`. `18` is parsed as `1` and the rest of it discarded while `10` will be parsed as base 8 and the output is in base-10. – VLAZ Dec 29 '19 at 22:50
  • Also relevant: [Why does parseInt('dsff66',16) return 13?](https://stackoverflow.com/questions/26017371/why-does-parseintdsff66-16-return-13) – VLAZ Dec 29 '19 at 22:58
  • @VLAZ At the same time, the code does use generator functions – randomvalue Dec 29 '19 at 22:59
  • @randomvalue and generator functions are irrelevant to the behaviour you describe. The code also uses variable declaration, loops, template strings, as well as console logging, yet you've not made the question about any of these aspects. – VLAZ Dec 29 '19 at 23:00
  • @VLAZ if you look, my question does concern parsing, which might have something to do with questions about the patterns I mentioned – randomvalue Dec 29 '19 at 23:10
  • @randomvalue yes. Again: *parsing* is relevant but *generator functions* are not. The title suggests that the behaviour is connected to generators yet removing that will leave you with the same behaviour - `parseInt("10", 8)` and `parseInt("19", 8)` work the same way regardless of whether or not the code is inside a generator function. – VLAZ Dec 29 '19 at 23:14
  • yea you're right – randomvalue Dec 29 '19 at 23:52

3 Answers3

0

See MDN:

If parseInt encounters a character that is not a numeral in the specified radix, it ignores it and all succeeding characters and returns the integer value parsed up to that point.

Therefore, when using parseInt(i, 8), once any character 8 or above is encountered (so, 8 or 9), parsing will stop, and only what was parsed so far will be returned. So:

18 -> 1

19 -> 1

28 -> 2

29 -> 2

The invalid character (and any characters that follow it) are just dropped. For these examples, only the tens place was valid, so only the character at the tens place is returned.

Similarly:

119 -> 9

console.log(parseInt('119', 8));

because the leading non-invalid characters, 11, when parsed as octal, are (8 ** 1 * 1) + (8 ** 0 * 1) = 8 + 1 = 9.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
0

You parse the value as octal number, because you gave a radix of 8 with parseInt.

console.log(parseInt(20, 8));
//                       ^ treat the value as octal number
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

As octal numbers only have digits up to 7, any string that has an "8" or "9" will only be parsed up to, but not including, that character. So "29" will be interpreted as just "2" -- the "9" is ignored.

That "24" becomes 20 as decimal number is just normal octal-to-decimal conversion: Octal "24" is 2*8+4 = 20.

trincot
  • 317,000
  • 35
  • 244
  • 286