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

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

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

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

HTML5

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

JavaScript

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

Q&A

解決済

1回答

551閲覧

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

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ブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿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

1'use strict'; 2 3 4const current = new Date(); 5const year = current.getFullYear(); 6const month = current.getMonth() + 1; 7 8 9// カレンダーの表示 10let cHeader = document.getElementById('cHeader'); 11const cMain = document.getElementById('cMain'); 12addCalendar(cHeader, cMain, year, month); 13addHeader(cHeader); 14 15function addCalendar(cHeader, cMain, year, month) { 16 // 現在カレンダーが追加されている場合は一旦削除する 17 cMain.innerHTML = null; 18 19 // カレンダーの要素を追加 20 cMain.appendChild(cTable(year, month)); 21 cMain.appendChild(cPrev(year, month)); 22 cMain.appendChild(cNext(year, month)); 23} 24 25function addHeader(cHeader){ 26 cHeader.innerHTML = null; 27 cHeader.appendChild(generateCalendarHeader()); 28 move_timer(); 29} 30 31function move_timer(){ 32 setTimeout(addHeader, 1000); 33} 34 35function generateCalendarHeader() { //カレンダーのヘッダーを作成、月の移動の機能 36 37 // 見出しの追加 38 const cTitle = document.createElement('div'); 39 cTitle.className = 'cHeader_title'; 40 41 const cTitleText = document.createTextNode(todayTime()); 42 cTitle.appendChild(cTitleText); 43 44 // 横線の追加 45 const horizontal_line = document.createElement('hr'); 46 cTitle.insertAdjacentElement("beforeend", horizontal_line); 47 48 return cTitle; 49} 50 51function todayTime() { 52 // 今日の日時を取得 53 const today = new Date(); 54 const today_year = today.getFullYear(); 55 const today_month = today.getMonth() + 1; 56 const today_days = today.getDate(); 57 const today_weekday = today.getDay(); 58 const today_hours = today.getHours(); 59 const today_min = today.getMinutes(); 60 const today_sec = today.getSeconds(); 61 62 //曜日を文字に変換 63 const weekday_character = ['日', '月', '火', '水', '木', '金', '土']; 64 65 let today_time = ` ${today_year}${today_month}${today_days}日(${weekday_character[today_weekday]}${today_hours}${today_min}${today_sec}`; 66 67 return today_time; 68} 69 70function cTable(year, month) { 71 const weekdayData = ['日', '月', '火', '水', '木', '金', '土']; 72 //カレンダーの情報を取得 73 const calendarData = getMonthCalendar(year, month); 74 75 var i = calendarData[0].weekday; // 初日の曜日を取得 76 // カレンダー上の初日より前を埋める 77 while (i > 0) { 78 i--; 79 calendarData.unshift({ 80 day: '', 81 weekday: i 82 }); 83 } 84 var i = calendarData[calendarData.length - 1]['weekday']; // 末日の曜日を取得 85 // カレンダー上の末日より後を埋める 86 while (i < 5) { 87 i++; 88 calendarData.push({ 89 day: '', 90 weekday: i 91 }); 92 } 93 94 // カレンダーの要素を生成 95 const cTable = document.createElement('table'); 96 cMain.insertAdjacentElement('beforeend', cTable) 97 cTable.className = 'calendar-table'; 98 99 let insertData = ''; 100 // 曜日部分の生成 101 insertData += '<thead>'; 102 insertData += '<tr><th colspan = "7">'; 103 insertData += `${year}年 ${month}`; 104 insertData += '</th></tr>'; 105 insertData += '<tr>'; 106 for (let i = 0; i < weekdayData.length; i++) { 107 insertData += '<th>'; 108 insertData += weekdayData[i]; 109 insertData += '</th>'; 110 } 111 insertData += '</tr>'; 112 insertData += '</thead>'; 113 114 // 日付部分の生成 115 insertData += '<tbody>'; 116 for (let i = 0; i < calendarData.length; i++) { 117 if (calendarData[i].weekday <= 0) { 118 insertData += '<tr>'; 119 } 120 insertData += '<td>'; 121 insertData += calendarData[i]['day']; 122 insertData += '</td>'; 123 if (calendarData[i]['weekday'] >= 6) { 124 insertData += '</tr>'; 125 } 126 } 127 insertData += '</tbody>'; 128 129 cTable.innerHTML += insertData; 130 131 return cTable; 132} 133 134function cPrev(year, month) { 135 const prevMonth = new Date(year, (month - 1)); 136 prevMonth.setMonth(prevMonth.getMonth() - 1); 137 138 // 前月ボタンの追加 139 let cPrev = document.createElement('button'); 140 cPrev.className = 'cHeader_prev' 141 const page_move_prev = document.createElement('img'); 142 page_move_prev.id = 'move_prev'; 143 page_move_prev.src = "image/page_move.png"; 144 cPrev.appendChild(page_move_prev); 145 // 前月ボタンをクリックした時のイベント設定 146 cPrev.addEventListener('click', function () { 147 addCalendar(cHeader, cMain, prevMonth.getFullYear(), (prevMonth.getMonth() + 1)); 148 }, false); 149 150 return cPrev; 151} 152 153function cNext(year, month) { 154 155 // 前月と翌月を取得 156 const nextMonth = new Date(year, (month - 1)); //与えられた月(month)は1~12月まであるが、コンピュータが処理できる月は0~11の範囲である。よって-1している。 157 nextMonth.setMonth(nextMonth.getMonth() + 1); 158 159 // 翌月ボタンの追加 160 const cNext = document.createElement('button'); 161 cNext.className = 'cHeader_next'; 162 const page_move_next = document.createElement('img'); 163 page_move_next.id = 'move_next'; 164 page_move_next.src = "image/page_move.png"; 165 cNext.insertAdjacentElement('beforeend', page_move_next); 166 167 // 翌月ボタンをクリックした時のイベント設定 168 cNext.addEventListener('click', function () { 169 addCalendar(cHeader, cMain, nextMonth.getFullYear(), (nextMonth.getMonth() + 1)); 170 }, false); 171 172 return cNext; 173} 174 175function getMonthCalendar(year, month) { //指定した月の日付と曜日を配列で返す 176 const firstDate = new Date(year, (month - 1), 1); //指定した月の初日の情報 177 const lastDay = new Date(year, (firstDate.getMonth() + 1), 0).getDate(); //指定した月の最終日の情報 178 const weekday = firstDate.getDay(); //初日の曜日を取得 179 180 const calendarData = []; //カレンダーの情報を格納 181 let weekdayCount = weekday; //曜日の格納 182 for (let i = 0; i < lastDay; i++) { 183 calendarData[i] = { // 連想配列、配列の中に連想配列が含まれている 184 day: i + 1, 185 weekday: weekdayCount 186 } 187 if (weekdayCount >= 6) { 188 weekdayCount = 0 189 } else { 190 weekdayCount++; 191 } 192 } 193 return calendarData; 194} 195 196

試したこと

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

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

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

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

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

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

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

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

m.ts10806

2022/09/19 11:29 編集

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

回答1

0

ベストアンサー

setTimeout(addHeader, 1000);addHeader 関数を呼び出すとき、関数に引数を渡していないので addHeader(cHeader)cHeaderundefined になりますよ。
addHeader() にして、グローバル変数の cHeader を参照するようにするのがいいと思います。

投稿2022/09/19 11:24

編集2022/09/19 11:25
shiracamus

総合スコア5406

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

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

maidchan12345

2022/09/19 15:00

確かにそうでした…。ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問