JavaScript  for..in, for..of チートシート

# Array, Object, String × for...in, for...of

配列も、オブジェクトも、文字列も、 for 文で回せるのが JavaScript のいいところなんだけど、in と of の２種類があって、どっちがどっちなのか忘れちゃうので、自分のためのチートシートを作った。

|for| Array | Object | String |
|:--:|:--:|:--:|:--:|
|in| index | key | index |
|of| value | SyntaxError |value |

追記：結論を書いちゃうと、
「いん」は「いんデックス」
「おぶ」は「ぶぁりゅ～」
と覚えればこのページを見なくても生きていける（ぉぃ


### Array + in -> index


```js
    for ( const i in [ 111, 222, 333 ] )  // Array + in -> index
    {
        console.log( i )                  // '0' '1' '2'
    }
```

ここでの注意点は、なんと`i`には数値(number)ではなく数字(string)がくるところ（なんでやねん！まぁ、気にせず計算はできちゃうんだけどね）


### Array + of -> value

```js
    for ( const v of [ 111, 222, 333 ] )  // Array + of -> value
    {
        console.log( v )                  // 111 222 333
    }
```

index value 両方を得たい場合はこうするしかなくて

```js
    const ary = [ 111, 222, 333 ]
    for ( const i in ary )
    {
        console.log( i, ary[i] )          // 0 111 1 222 2 333
    }
```

であれば手っ取り早いのは `.forEach()` なんだけど、

```js
    [ 111, 222, 333 ].forEach( (v,i)=>    // value, index の順番
    {
        console.log( i, v )               // 0 111 1 222 2 333
    } )
```

でも、`.forEach()` 使うくらいなら、 `.map()` を使うかなぁ。
なんというか、戻り値を使わないのがもったいなくて。貧乏性？

```js
    console.log(
        [ 111, 222, 333 ].map( (v,i)=>[i,v] )
    )                                    // [ [ 0, 111 ], [ 1, 222 ], [ 2, 333 ] ]
```

### range() 


残念ながら、いまの JavaScript には他の言語に見られるような便利な range() は無いようです。
代わりに以下のようなコードが使われているようです。for...in なのか for...of なのかわかりにくいですよね。

for...in を使いたい場合はこう書いて、

```js
    for ( const i in Array.from(Array(5)) )  // Array + in -> index
    {
        console.log( i )                // '0' '1' '2' '3' '4'  注意：文字
    }
```

`for ( const i in Array(5) )`ではダメなんです、謎。（これをおっけーにしてほしいなぁ、、、お願いします🙏）

for...of を使いたい場合は、

```js
    for ( const v of Array(5).keys() )  // Array + of -> value
    {
        console.log( v )                // 0 1 2 3 4 注意：数値
    }
```

こっちのほうが数値だし、短くてよさげですが、この書き方だと in はダメで of ならおっけーってところが解せない感じ。ちょっと覚えにくいし、どっちもパッと見て直感的にどう動くのか理解できないと使えないと思うんですよね。


### Object + in -> key

```js
    for ( const k in { a: 111, b: 222, c: 333 } )  // Object + in -> key
    {
        console.log( k )                           // a b c
    }
```

### Object + of -> SyntaxError

実行できません

```js
    for ( const v of { a: 111, b: 222, c: 333 } )  // Object + of -> SyntaxError
    {             ^^
        console.log( v )                           //
    }
```

両方ほしいときは、まぁ、こうするかな。

```js
    const obj = { a: 111, b: 222, c: 333 }
    for ( const k in obj )
    {
        console.log( k, obj[k] )  // a 111 b 222 c 333
    }
```

もしくは、

```js
    const obj = { a: 111, b: 222, c: 333 }
    Object.keys( obj ).forEach( k=> // [ 'a', 'b', 'c' ]
    {
        console.log( k, obj[k] )  // a 111 b 222 c 333
    } )
```

### String + in -> index


```js
    for ( const i in 'abcあいう' )  // String + in -> index
    {
        console.log( i )            // '0' '1' '2' '3' '4' '5'
    }
```


### String + of -> value

```js
    for ( const v of 'abcあいう' )  // String + of -> value
    {
        console.log( v )            // 'a' 'b' 'c' 'あ' 'い' 'う'
    }
```

残念ながら、以下のようには書けなくて、

```js
    'abcあいう'.forEach( (v,i)=>    // TypeError: .forEach is not a function
    {
        console.log( i, v )         
    } )
```

`.split('')` を使って回避することはできる。しかし、空の文字列で分割って、、、、どうなんだろう。

```js
    'abcあいう'.split('').forEach( (v,i)=>    // value, index の順番
    {
        console.log( i, v )         // 0 a  1 b  2 c  3 あ  4 い  5 う
    } )
```

以下、参考

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for...in

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