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

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

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

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

解決済

【JS】setTimeoutを実行したら、最初にconstで宣言した定数がundefindedになる

maidchan12345
maidchan12345

総合スコア1

CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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

1回答

0リアクション

1クリップ

217閲覧

投稿2022/09/19 11:16

前提

JSとCSS、HTMLでカレンダーと現在日時をブラウザ上に表示できるようプログラミングしています。
setTimeoutを用いて現在時間を非同期処理で更新しようとおもっているのですが、最初に宣言した定数cHeaderがsetTimeoutで呼び出された関数addHeader内でundefinedとなってしまいエラーが発生してしまいます。
ブラウザを更新した際に最初に読み込まれたaddHeaderはcHeaderはしっかりと読み込まれ、エラーは発生しません。2回目以降のsetTimeoutを用いてaddHeaderを読み込むときのみエラーが発生します。
cHeaderを宣言する位置を、addHeader内にすると問題なくプログラムは実行されます。

実現したいこと

setTimeoutを用いて、現在時刻を非同期処理で更新できるようにしたい。
setTimeoutで関数addHeaderが読み込まれても定数cHeaderがundefinededにならないようにしたい。

発生している問題・エラーメッセージ

Uncaught TypeError: Cannot set properties of undefined (setting 'innerHTML') at addHeader (script.js:26:23)

該当のソースコード

JavaScript

'use strict'; const current = new Date(); const year = current.getFullYear(); const month = current.getMonth() + 1; // カレンダーの表示 let cHeader = document.getElementById('cHeader'); const cMain = document.getElementById('cMain'); addCalendar(cHeader, cMain, year, month); addHeader(cHeader); function addCalendar(cHeader, cMain, year, month) { // 現在カレンダーが追加されている場合は一旦削除する cMain.innerHTML = null; // カレンダーの要素を追加 cMain.appendChild(cTable(year, month)); cMain.appendChild(cPrev(year, month)); cMain.appendChild(cNext(year, month)); } function addHeader(cHeader){ cHeader.innerHTML = null; cHeader.appendChild(generateCalendarHeader()); move_timer(); } function move_timer(){ setTimeout(addHeader, 1000); } function generateCalendarHeader() { //カレンダーのヘッダーを作成、月の移動の機能 // 見出しの追加 const cTitle = document.createElement('div'); cTitle.className = 'cHeader_title'; const cTitleText = document.createTextNode(todayTime()); cTitle.appendChild(cTitleText); // 横線の追加 const horizontal_line = document.createElement('hr'); cTitle.insertAdjacentElement("beforeend", horizontal_line); return cTitle; } function todayTime() { // 今日の日時を取得 const today = new Date(); const today_year = today.getFullYear(); const today_month = today.getMonth() + 1; const today_days = today.getDate(); const today_weekday = today.getDay(); const today_hours = today.getHours(); const today_min = today.getMinutes(); const today_sec = today.getSeconds(); //曜日を文字に変換 const weekday_character = ['日', '月', '火', '水', '木', '金', '土']; let today_time = ` ${today_year}${today_month}${today_days}日(${weekday_character[today_weekday]}${today_hours}${today_min}${today_sec}`; return today_time; } function cTable(year, month) { const weekdayData = ['日', '月', '火', '水', '木', '金', '土']; //カレンダーの情報を取得 const calendarData = getMonthCalendar(year, month); var i = calendarData[0].weekday; // 初日の曜日を取得 // カレンダー上の初日より前を埋める while (i > 0) { i--; calendarData.unshift({ day: '', weekday: i }); } var i = calendarData[calendarData.length - 1]['weekday']; // 末日の曜日を取得 // カレンダー上の末日より後を埋める while (i < 5) { i++; calendarData.push({ day: '', weekday: i }); } // カレンダーの要素を生成 const cTable = document.createElement('table'); cMain.insertAdjacentElement('beforeend', cTable) cTable.className = 'calendar-table'; let insertData = ''; // 曜日部分の生成 insertData += '<thead>'; insertData += '<tr><th colspan = "7">'; insertData += `${year}年 ${month}`; insertData += '</th></tr>'; insertData += '<tr>'; for (let i = 0; i < weekdayData.length; i++) { insertData += '<th>'; insertData += weekdayData[i]; insertData += '</th>'; } insertData += '</tr>'; insertData += '</thead>'; // 日付部分の生成 insertData += '<tbody>'; for (let i = 0; i < calendarData.length; i++) { if (calendarData[i].weekday <= 0) { insertData += '<tr>'; } insertData += '<td>'; insertData += calendarData[i]['day']; insertData += '</td>'; if (calendarData[i]['weekday'] >= 6) { insertData += '</tr>'; } } insertData += '</tbody>'; cTable.innerHTML += insertData; return cTable; } function cPrev(year, month) { const prevMonth = new Date(year, (month - 1)); prevMonth.setMonth(prevMonth.getMonth() - 1); // 前月ボタンの追加 let cPrev = document.createElement('button'); cPrev.className = 'cHeader_prev' const page_move_prev = document.createElement('img'); page_move_prev.id = 'move_prev'; page_move_prev.src = "image/page_move.png"; cPrev.appendChild(page_move_prev); // 前月ボタンをクリックした時のイベント設定 cPrev.addEventListener('click', function () { addCalendar(cHeader, cMain, prevMonth.getFullYear(), (prevMonth.getMonth() + 1)); }, false); return cPrev; } function cNext(year, month) { // 前月と翌月を取得 const nextMonth = new Date(year, (month - 1)); //与えられた月(month)は1~12月まであるが、コンピュータが処理できる月は0~11の範囲である。よって-1している。 nextMonth.setMonth(nextMonth.getMonth() + 1); // 翌月ボタンの追加 const cNext = document.createElement('button'); cNext.className = 'cHeader_next'; const page_move_next = document.createElement('img'); page_move_next.id = 'move_next'; page_move_next.src = "image/page_move.png"; cNext.insertAdjacentElement('beforeend', page_move_next); // 翌月ボタンをクリックした時のイベント設定 cNext.addEventListener('click', function () { addCalendar(cHeader, cMain, nextMonth.getFullYear(), (nextMonth.getMonth() + 1)); }, false); return cNext; } function getMonthCalendar(year, month) { //指定した月の日付と曜日を配列で返す const firstDate = new Date(year, (month - 1), 1); //指定した月の初日の情報 const lastDay = new Date(year, (firstDate.getMonth() + 1), 0).getDate(); //指定した月の最終日の情報 const weekday = firstDate.getDay(); //初日の曜日を取得 const calendarData = []; //カレンダーの情報を格納 let weekdayCount = weekday; //曜日の格納 for (let i = 0; i < lastDay; i++) { calendarData[i] = { // 連想配列、配列の中に連想配列が含まれている day: i + 1, weekday: weekdayCount } if (weekdayCount >= 6) { weekdayCount = 0 } else { weekdayCount++; } } return calendarData; }

試したこと

宣言の方法をletを用いた。
宣言する位置を変更した。

補足情報(FW/ツールのバージョンなど)

ブラウザ:Chrome
エディタ:VScode
両者最新バージョンを使用

以下のような質問にはリアクションをつけましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

リアクションが多い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

m.ts10806

2022/09/19 11:29 編集

そもそも実行引数渡してないのでは →あぁ回答つきましたね。

まだ回答がついていません

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

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

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

CSS3

CSS(Cascading Style Sheet)の第3版です。CSS3と略されることが多いです。色やデザインを柔軟に変更することが可能になります。

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

JavaScript

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