Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

let と const について >> ループと反復処理 #567

Closed
mimosafa opened this issue Nov 13, 2018 · 3 comments · Fixed by #852
Closed

let と const について >> ループと反復処理 #567

mimosafa opened this issue Nov 13, 2018 · 3 comments · Fixed by #852

Comments

@mimosafa
Copy link

for … in ならびに、for … of の例示コードの中で、key, value が const のもとで宣言されている(ように見える)のが、どうしても理解できませんでした。
コラムでその辺りの合点が得られるのかと期待したのですが、そうはいかず…
どうかその辺りのご解説をいただければ幸いです。

URL : https://github.com/asciidwango/js-primer/blob/master/source/basic/loop/README.md

@azu
Copy link
Collaborator

azu commented Nov 13, 2018

@mimosafa フィードバックありがとうございます。

このケースだとlet iなのに

let total = 0; // 初期値は0
for (let i = 0; i < 10; i++) {
    total += i + 1; // 1...10
}
console.log(total); // => 55

次のケースだとconst key となぜできるかという話ですかね?

const object = {
    "a": 1,
    "b": 2,
    "c": 3
};
for (const key in object) {
    const value = object[key];
    console.log(`key:${key}, value:${value}`);
}

書いてるときに確か解説を一度入れようとして、きれいな解説が思いつかなくて結局入らなかった感じがしますね。
(どこかにログが残ってないか探しましたがなさそうでした)

原理的にはforループにかかれているconst keyの部分はループのたびに別々のスコープとなるため、毎回同じ名前で定義できるという感じですね。

例えば次のコードはconst item123と値が入ってループします。

const array = [1,2,3]
for (const item in array) {
    console.log(item);
}

このループを擬似的に展開すると次のようになります。
ループのたびに毎回新しいブロック{}で囲まれて実行されます。

const array = [1,2,3]
// 1回めのループ
{ 
   const item = 1;
   console.log(item);
}
// 2回目のループ
{
   const item = 2;
   console.log(item);
}
// 3回目のループ
{
   const item = 3;
   console.log(item);
}

ループ内で定義したitemは外から参照できないのも同じ理由です。

const array = [1,2,3]
for (const item in array) {
    console.log(item);
}
// ここでitemを参照しようとしても、ループ内はブロックスコープで囲まれているからアクセスできない。
console.log(item); // => ReferenceError: item is not defined

forループごとに別々のブロック{}で実行されるため、おなじitemという名前で定義できる感じになります。(ブロック{}があれば同じ名前が使えるのは、letconstはブロックスコープ https://jsprimer.net/basic/function-scope/#block-scope だからという話です)

一方で、最初のlet iletになっているのは、このi++ インクリメントされているからですね。
const i = 1; i++がエラーになるからletになっているという理由です。
constで定義した変数に対しては宣言後に代入(インクリメントも代入の一部)はできないからという理由です

let total = 0; // 初期値は0
for (let i = 0; i < 10; i++) {
    total += i + 1; // 1...10
}
console.log(total); // => 55

const for loop why とかで検索すると多分いろいろな解説がでてくると思います。

ここで解説がなかったのは、コードの見た目と動きが違ったり、スコープの概念を知ってないと理解できない挙動だったりするからですね…
なんとかコラムで解説できないかを考えてみます。

@mimosafa
Copy link
Author

ありがとうございます!理解できました。
「関数とスコープ」で解説されてましたね。コラムでなくてもその導線が提示されていれば(私的には)良いと思います。

@azu
Copy link
Collaborator

azu commented Jun 28, 2019

#852 で「関数とスコープ」への動線を追加しました

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants