for-of の変数宣言とスコープ
- カテゴリ:
- JavaScript
- コメント数:
- Comments: 0
◆ of の前後で同じ変数名を使えない
◆ 仮の名前で受け取ってスコープ内で宣言すれば使える
◆ 仮の名前で受け取ってスコープ内で宣言すれば使える
普通の for-of 文はこんなのです
このときの item 変数はブロックスコープの内側に作られて 内側に宣言する変数と同じような扱いだと思ってました
for-of 文を抜けるとアクセスできないですし
なのでこういうふうに of の右側と同じ変数名を使おうとしたのですが
Uncaught ReferenceError: Cannot access 'items' before initialization
というエラーが出ました
items という名前が問題になってそうです
にして名前を変えてみると問題なく動きました
普段は内側スコープの変数で外側スコープの変数を隠すようなことは積極的にはしないので あまり自信ないですが昔からずっとこんな挙動でしたっけ?
考えてみれば for 文の () 内で分割代入せず中の処理の最初でやってることが多いです
スコープ的には同じことなのでエラーになると思いながらも試してみると
エラーになりませんでした
これでも items という変数をスコープ内に作ってるのですが こっちは問題ないようです
もう少し試していると
これなら問題ないようでした
外側スコープの変数名と被るからダメってわけでもないようです
状況として of の前後で同じ変数名がある場合にエラーになるようです
内部的には
みたいな処理になっていて const で宣言すると同時に親スコープの変数を参照しようとしてるのかもしれません
イテレータオブジェクトだけ渡されて親スコープの items には直接アクセスしなさそうに思ってましたが こういうことをしてるなら納得です
気をつけようにも分割代入が複雑になってくると混ざってしまうとことがありえます
中で分割代入すれば問題ないので 一旦適当な変数で受け取るほうがいいのかもしれません
const items = [1, 2]
for (const item of items) {
console.log(item)
}
このときの item 変数はブロックスコープの内側に作られて 内側に宣言する変数と同じような扱いだと思ってました
for-of 文を抜けるとアクセスできないですし
なのでこういうふうに of の右側と同じ変数名を使おうとしたのですが
const items = [
{ value: 1, items: [] },
{ value: 2, items: [10, 20] },
]
for (const { value, items } of items) {
console.log(value)
}
Uncaught ReferenceError: Cannot access 'items' before initialization
というエラーが出ました
items という名前が問題になってそうです
for (const { value, items: foo } of items) {
にして名前を変えてみると問題なく動きました
普段は内側スコープの変数で外側スコープの変数を隠すようなことは積極的にはしないので あまり自信ないですが昔からずっとこんな挙動でしたっけ?
考えてみれば for 文の () 内で分割代入せず中の処理の最初でやってることが多いです
スコープ的には同じことなのでエラーになると思いながらも試してみると
const items = [
{ value: 1, items: [] },
{ value: 2, items: [10, 20] },
]
for (const item of items) {
const { value, items } = item
console.log(value)
}
エラーになりませんでした
これでも items という変数をスコープ内に作ってるのですが こっちは問題ないようです
もう少し試していると
const items = [
{ value: 1, items: [] },
{ value: 2, items: [10, 20] },
]
const items2 = items
for (const { value, items } of items2) {
console.log(value)
}
これなら問題ないようでした
外側スコープの変数名と被るからダメってわけでもないようです
状況として of の前後で同じ変数名がある場合にエラーになるようです
内部的には
const items = [1, 2, 3]
{
const items = getNext(items)
//
}
みたいな処理になっていて const で宣言すると同時に親スコープの変数を参照しようとしてるのかもしれません
イテレータオブジェクトだけ渡されて親スコープの items には直接アクセスしなさそうに思ってましたが こういうことをしてるなら納得です
気をつけようにも分割代入が複雑になってくると混ざってしまうとことがありえます
const items = [[{ val1: 1, val2: { val3: 10, items: [], val4: 20 } }]]
for (const [{ val1, val2: { val3, items, val4 } }] of items) { }
中で分割代入すれば問題ないので 一旦適当な変数で受け取るほうがいいのかもしれません