質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

4回答

907閲覧

JavaScript で let を下階層 if 内で再宣言すると値がリセットされてしまう

owly

総合スコア3

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2020/10/08 17:32

編集2020/10/08 17:59

以下で➀と➁のように同じ変数名でletを宣言したとします。

なぜ➁がある場合に、結果から「元のデータ」のobj1がなくなるのでしょうか?

Javascript

1const obj1 = {initdata:'元のデータ'}; 2let obj2 = {}; // ➀ 3 4if( true ){ 5 6 let obj2 = {}; // ➁ 7 8 if( true ){ 9 obj2 = obj1; 10 } 11 12} 13 14obj2.newdata = '追加されたデータ'; 15console.log(obj2);

上記の➁を削除するときちんと「元のデータ」のobj1があります。
つまり➁がobj1を削除する要因になっているのですが、なぜなのかわかりません。

だって➁はobj2を初期化して空のオブジェクトとして扱っているだけで、その下のobj2 = obj1によってobj2にはobj1が入るはずですから、obj1を削除する要因になるという理屈が理解できないのです。

・なぜ➁があると、obj2 = obj1による代入が、最後のobj2に効かないのか?(➀の宣言に対して効かないのか?)
・なぜ➁がないと、obj2 = obj1による代入が、最後のobj2に効くのか?(➀の宣言に対して効くのか?)

という方向でご解説頂けましたら幸いです。(➁の有無で、➀の宣言に対して効いたり効かなかったり、とスコープの範囲が変わる点が納得いきません)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

②がある場合は、
obj2は、ifブロック内スコープ限定の変数となり、そもそも、
**その外側スコープのobj2**に代入が行えなくなるからです。

obj2 = obj1による代入が、最後のobj2に効かないのか?

効かないのではなく、そもそも別物になる、ってことです。

そういった事を考えるならば、
今回のケースでは特に、内側スコープで、その外側スコープの変数と同名の変数は宣言すべきではないと言えます。

今回のように短いコードなら特に問題なくとも、
規模が大きくなればなるほど、
どこで何をやっているかわけわからなくなるでしょう。

投稿2020/10/08 22:37

編集2020/10/09 04:30
miyabi_takatsuk

総合スコア9555

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

think49

2020/10/09 04:05

> グローバルスコープのobj2に代入が行えなくなるからです。 letを使用している限り、グローバル変数が定義される事はありません。 letはグローバルコード上であっても、グローバルスコープの一つ下にブロックスコープを形成しているかのように振る舞います。 つまり、グローバルオブジェクトのプロパティ(=グローバル変数)にはなりません。
miyabi_takatsuk

2020/10/09 04:39 編集

そうでした、グローバルとローカルと言っちゃうと、varと同じ仕様になっちゃいますね 汗 回答修正しました。
guest

0

スコープチェーン

ブロックスコープスコープチェーンを調べる事をお勧めします。

スコープチェーンによって、先に発見する変数は「if文内のobj2」です。

let

let同一スコープ上で同じ名前の変数が定義されることを許可しません。

JavaScript

1let obj2 = {}; 2let obj2 = []; // SyntaxError

let で同名変数を定義しても SyntaxError にならないのなら、別のスコープにある変数を定義している事になります。

Re: owly さん

投稿2020/10/09 03:59

think49

総合スコア18189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

つまり➁がobj1を削除する要因になっているのですが

なっていません。

ブロック内でのobj2は➁のほうだけを指していて、➀のobj2はそもそも変化していません(同じ名前ですが両者は別な変数として振る舞います)。

投稿2020/10/09 01:42

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2020/10/09 01:45

> ➁の有無で、➀の宣言に対して効いたり効かなかったり、とスコープの範囲が変わる点が納得いきません 何に納得がいかないのかわからないですが、➁の宣言がある場合、ブロック内でのobj2は➁を指し、➀をブロック内から読み書きすることはできません。
maisumakun

2020/10/09 01:46

> ➁はobj2を初期化して空のオブジェクトとして扱っているだけで 違います。全く同じ名前の、「別な変数」を作成しています。
owly

2020/10/09 03:06 編集

直近の変数にだけ効くということでしょうか? 直近の➁の obj2 にだけ効くから、一つ遠い➀には`obj2 = obj1`が効かない もし➁がなければ➀が直近となり、➀に`obj2 = obj1`が効く というイメージですか?
miyabi_takatsuk

2020/10/11 01:10

効く、効かないの問題ではなく、 ①と②は別物になるということをご理解下さい。 ②を定義してしまった時点で、 同スコープでは、①に対して読み書きできません。
think49

2020/10/11 03:33 編集

「obj2 = obj1;」において、スコープチェーン上で発見される変数は➁です。 また、①と②は名前衝突している為、①を参照する事は出来ません。
guest

0

let
ちょうど質問者様の質問と同じ内容で解説があります。
ご参考にされてはいかがでしょう。

投稿2020/10/08 17:38

kuma_kuma_

総合スコア2506

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問