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

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

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

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

Q&A

解決済

3回答

942閲覧

関数宣言後に関数内で利用する配列を定義しても良い理由が分かりません

tanakashouzoux

総合スコア52

JavaScript

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

1グッド

0クリップ

投稿2020/06/01 06:51

下記コードの「chechResult関数」の中で使われている「panels[0]」「panels[1]」「panels[2]」は関数宣言後に出てくる配列なので、関数宣言時には定義されておらずエラーが出ると思ったのですが、どうしてエラーが出ないのでしょうか?

もう考えても頭がこんがらがり過ぎて頭がおかしくなってしまいました
どなたか教えて頂けると幸いですm(__)m

javascript

1'use strict'; 2 3{ 4 class Panel { 5 constructor() { 6 const section = document.createElement('section'); 7 section.classList.add('panel'); 8 9 this.img = document.createElement('img'); 10 this.img.src = this.getRandomImage(); 11 12 this.timeoutId = undefined; 13 14 this.stop = document.createElement('div'); 15 this.stop.textContent = 'STOP'; 16 this.stop.classList.add('stop'); 17 this.stop.addEventListener('click', () => { 18 clearTimeout(this.timeoutId); 19 20 panelsLeft--; 21 22 if (panelsLeft === 0) { 23 checkResult(); 24 } 25 }); 26 27 section.appendChild(this.img); 28 section.appendChild(this.stop); 29 30 const main = document.querySelector('main'); 31 main.appendChild(section); 32 } 33 34 getRandomImage() { 35 const images = [ 36 'img/seven.png', 37 'img/bell.png', 38 'img/cherry.png', 39 ]; 40 return images[Math.floor(Math.random() * images.length)]; 41 } 42 43 spin() { 44 this.img.src = this.getRandomImage(); 45 this.timeoutId = setTimeout(() => { 46 this.spin(); 47 }, 50); 48 } 49 } 50 51 function checkResult() { 52 if (panels[0].isUnmatched(panels[1], panels[2])) { 53 panels[0].unmatch(); 54 } 55 if (panels[1].isUnmatched(panels[0], panels[2])) { 56 panels[1].unmatch(); 57 } 58 if (panels[2].isUnmatched(panels[0], panels[1])) { 59 panels[2].unmatch(); 60 } 61 } 62 63 const panels = [ 64 new Panel(), 65 new Panel(), 66 new Panel(), 67 ]; 68 69 let panelsLeft = 3; 70 71 const spin = document.getElementById('spin'); 72 spin.addEventListener('click', () => { 73 panels.forEach(panel => { 74 panel.spin(); 75 }); 76 }); 77}
momon-ga👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

これも巻き上げです。

constの巻き上げの場合は、

  • 宣言としては同じスコープで有効
  • 値へのアクセスは、アクセスするまでのタイミングで代入が行われていれば有効

ということになります。

checkResultが実行されるのはイベントハンドラ経由なので、panelsへの代入が済んでからになります。

投稿2020/06/01 07:06

maisumakun

総合スコア146018

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

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

tanakashouzoux

2020/06/01 07:30

本当に何十回もご回答ありがとうございますm(__)m 「宣言としては同じスコープで有効」ということは、このconst panels配列も最初に宣言されているのと同じという事なのでしょうか?? 「値へのアクセスは、アクセスするまでのタイミングで代入が行われていれば有効」ということは、checkResult関数内でpanels[0]、panels[1]、panels[2]が記述された時にはpanelsが宣言されていなくても、const panels実行時までに宣言がされていればエラーが出ずにそのまま使えるということなのでしょうか??
maisumakun

2020/06/01 07:33

> 「宣言としては同じスコープで有効」ということは、このconst panels配列も最初に宣言されているのと同じという事なのでしょうか?? そうですね、ただしconstの代入前のタイミングで値を読もうとするとReferenceErrorとなります。 後半もそのとおりです。
tanakashouzoux

2020/06/01 07:49

何度も何度も本当にありがとうございますm(__)m お陰様で理解が深まりました!!! ちなみに「constの代入前のタイミングで値を読もうとするとReferenceErrorとなります。」とのことですが、ということはcheckResult関数内でpanels[0]、panels[1]、panels[2]が記述された時にはエラーとなる値が読み込まれているということなのでしょうか??
maisumakun

2020/06/01 07:52

> checkResult関数内でpanels[0]、panels[1]、panels[2]が記述された時にはエラーとなる値が読み込まれているということなのでしょうか?? 関数宣言だけでは実行されないので、値は読み込まれません。
tanakashouzoux

2020/06/01 07:59

ご丁寧にありがとうございますm(__)m 「関数宣言だけでは実行されないので、値は読み込まれません。」ということは、関数の中で使う値は宣言時には読み込まれず、実行時に初めて読み込まれるということで合ってますでしょうか?
tanakashouzoux

2020/06/01 08:05

何度も本当にありがとうございます maisumakunさんもし良ければ上記知識が得られる書籍やサイト等ご存知であれば教えて頂けないでしょうか? 自分なりに調べたり本を読んだりしているつもりなのですが、上記の様な知識は得られなかったもので...
guest

0

Panelが宣言されていて、その後でnew Panelで3つインスタンスをつくっている
だけのように見えます。Panelクラスの中でpanels配列は参照されていませんよね?

投稿2020/06/01 06:55

yambejp

総合スコア116724

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

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

tanakashouzoux

2020/06/01 07:00

ご回答ありがとうございますm(__)m 「Panelが宣言されていて、その後でnew Panelで3つインスタンスをつくっている だけのように見えます。」これは私もその様に考えることが出来ます Panelクラスの中のfunction checkResult(){};の中でpanels配列は参照していることにならないのでしょうか???
guest

0

const panelsの前でcheckResult();を実行すればエラーになると思いますが、試されましたか?

投稿2020/06/01 06:54

kei344

総合スコア69606

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

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

tanakashouzoux

2020/06/01 06:57

早速のご回答ありがとうございますm(__)m 恥ずかしながら試しておりませんで、kei344さんに教えて頂いてから試したところエラーになりました どうしてcheckResult();だとエラーで、function checkResult(){};だとエラーが出ないのでしょうか?? function checkResult(){};の処理内を読み込んだ時点では同様にpanelsは定義されていないと思うのですが・・・
kei344

2020/06/01 07:00

function checkResult(){}は関数を定義しているだけで中身の実行はされないからです。 たとえば、function checkResult(){alert('!!!');} とか定義するだけでalertが実行されないでしょう。
tanakashouzoux

2020/06/01 07:02

何度もご回答ありがとうございます! 定義の段階では未定義の変数や配列を使っても大丈夫で、実行の段階では未定義の変数や配列を使ったらダメということなのでしょうか...??
kei344

2020/06/01 07:05

そうですね。コードが実行される時点で評価されます。
tanakashouzoux

2020/06/01 07:31

わざわざ繰り返しご回答頂きありがとうございますm(__)m 全然知りませんでした・・・ そういった知識はどこで学ぶことが出来るのでしょうか? 私が今まで読んだ本やサイトにはここまで詳しい話が載っていなくて...
kei344

2020/06/01 08:07

・コードは基本的に上から順番(書いてある順番)に処理される ・関数は呼び出すまで実行されない ・関数は呼び出されたら関数コードの上から順番に処理される ・JavaScriptはイベントで動くので、イベントが起こる前に関数を登録しておく ・イベントが起こると、登録した関数群が上から順番に処理される という話であれば、「プログラムってどうやって動く?」みたいな部分で触れられているかもしれません。 非同期処理などが加わると、「今その変数に値があるか」は意識する必要があるので、そのあたりで(私は)学習した可能性もあります。
tanakashouzoux

2020/06/01 08:10

わざわざご丁寧にありがとうございます 教えて頂いた「プログラムってどうやって動く?」「非同期処理」この辺りをもっと勉強してみようと思います! 本当にありがとうございますm(__)m
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問