<script>
let x = "arr"
if(x){
{arr: {forEach: function forEach(fn, a){for(const [k, v] of a.entries()){fn(v, k)}}}}[x].forEach(e => console.log(e), [1, 2, 3])
}
if(x) {arr: {forEach: function forEach(fn, a){for(const [k, v] of a.entries()){fn(v, k)}}}}[x].forEach(e => console.log(e), [1, 2, 3])
</script>
上は if の中だから {} がオブジェクトで x に入った "arr" プロパティをとりだしてるから forEach プロパティの入ったオブジェクトになって それの forEach プロパティを取り出しているので 実行する関数はその場で定義してる forEach で 1, 2, 3 がそれぞれ console.log で表示される
下は {} が if の {} になるから arr: はラベル扱い
次の {} はただのブロック扱いで中の forEach: もまたラベル扱い
forEach 関数を定義してるけどそれは使われず無視されて [x] の配列に対する組み込みの forEach になって 2 つ目の引数は意味ないから無視されて 配列の要素の "arr" だけ表示される
……と思いがちですが そうじゃないんです
上側の {} もブロック扱いで arr や forEach はラベル扱いです
結果 上下どちらも "arr" と表示されます
⇩ でも 1 とは表示されず ["x"] は関数ではないとエラーになります
<script>
{x: () => console.log(1)}["x"]()
</script>
Chrome に限らず IE や Firefox などでもです
何度見てもよくハマるんですよね
文が ( や [ から始まるときはセミコロンを前に書くのと同じように { から始まるときは () で囲むか ! や ~ などの単項演算子で始めると気をつけたほうが良さそうです
どっちかというとセミコロンより function(){} と同じで式とみなさせないといけないやつです