用 JavaScript 动态创建日历表格:createCalendar 实战解析(zh.javascript.info 经典任务)
文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载本篇文章以 zh.javascript.info 中「修改文档document」章节的经典任务「创建一个日历」为核心完整讲解createCalendar(elem, year, month)函数的实现思路、JavaScript 日期对象的正确用法以及通过innerHTML字符串拼接动态生成table的完整方案。读完本文你将掌握如何利用Date对象处理「月份从 0 开始」「每周从星期一开始」等日历排版的经典陷阱以及如何用一条 HTML 字符串干净地生成整张月历表格。任务背景它来自哪个章节该任务位于教程「修改文档document」小节07-modifying-document/article.md的练习区。在阅读本任务前你已经掌握了该章节的核心知识用document.createElement(tag)创建元素节点、用document.createTextNode(text)创建文本节点用node.append / prepend / before / after / replaceWith / remove等现代方法插入和移除节点用elem.insertAdjacentHTML(where, html)把 HTML 字符串按四个位置beforebegin、afterbegin、beforeend、afterend插入用elem.innerHTML一次性写入整段 HTML。「创建日历」这个任务本质上是把这些 DOM 修改能力与 JavaScript 日期计算结合起来的综合练习它不要求任何点击交互只要求根据给定的year和month在页面元素中生成一张结构正确的月历表格。任务要求原文编写一个函数createCalendar(elem, year, month)对该函数的调用应该使用给定的year/month创建一个日历并将创建的日历放入elem中创建的日历应该是一个表格table其中每一周用tr表示每一天用td表示表格顶部应该是带有星期名的th第一天应该是 Monday星期一依此类推直到 Sunday星期日例如createCalendar(cal, 2012, 9)应该在元素cal中生成对应的 2012 年 9 月日历附加说明本任务只要求生成日历不需要点击交互功能。任务对应的起始模板位于 source.view/index.html其中已经提供了div idcalendar/div占位容器和样式以及一个待你填充的函数骨架div idcalendar/div script function createCalendar(elem, year, month) { // ...your code that generates the calendar in elem... } createCalendar(calendar, 2012, 9); /script解决方案用一条 HTML 字符串构建整张表格官方解答见 solution.md 与 solution.view/index.html采用了一个非常简洁的策略我们将表格创建为字符串table.../table然后将其赋值给innerHTML。也就是说不逐格调用createElement/append来搭建 DOM 树而是先在内存中把整张表格的 HTML 拼成一条字符串最后一次性赋值给elem.innerHTML。对于这种结构规整、内容以日期数字为主的表格字符串拼接方式代码更短、可读性更好也省去了大量重复的 DOM 操作调用。核心算法五步官方解答将整个算法拆解为 5 步使用th创建带有星期名的表头创建日期对象d new Date(year, month-1)。它是month的第一天考虑到 JavaScript 中的月份从0开始而不是从1开始直到月份的第一天d.getDay()前面的几个单元格是空的。用td/td填充它们天数增长dd.setDate(d.getDate()1)。如果d.getMonth()还没到下一个月就将新的单元格td添加到日历中如果那天是星期日就添加新行/trtr如果该月结束但表格的行尚未填满就用空的td补齐。完整参考实现function createCalendar(elem, year, month) { let mon month - 1; // JS 中月份是 0..11而不是 1..12 let d new Date(year, mon); let table tabletrthMO/ththTU/ththWE/ththTH/ththFR/ththSA/ththSU/th/trtr; // 第一行的空格 // 从星期一 到 这个月的第一天 // * * * 1 2 3 4 for (let i 0; i getDay(d); i) { table td/td; } // 填充有实际日期的 td while (d.getMonth() mon) { table td d.getDate() /td; if (getDay(d) % 7 6) { // 星期日一周最后一天 - 换行 table /trtr; } d.setDate(d.getDate() 1); } // 补上月末之后剩余的空格填满最后一行 // 29 30 31 * * * * if (getDay(d) ! 0) { for (let i getDay(d); i 7; i) { table td/td; } } // 关闭表格 table /tr/table; elem.innerHTML table; } function getDay(date) { // 获取星期编号从 0星期一到 6星期日 let day date.getDay(); if (day 0) day 7; // 让星期日0变成最后一天 return day - 1; } createCalendar(calendar, 2012, 9);以createCalendar(calendar, 2012, 9)为例这段代码生成的 2012 年 9 月日历布局如下该月 1 号是星期六因此第一行以两个空格开头30 号是星期日因此最后一行恰好以 30 收尾无需补空格MO TU WE TH FR SA SU 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30配套样式渲染出的表格是否美观取决于 CSS。仓库给出的 solution.view/index.html 中提供了配套样式可以直接复用table { border-collapse: collapse; } td, th { border: 1px solid black; padding: 3px; text-align: center; } th { font-weight: bold; background-color: #E6E6E6; }其中border-collapse: collapse让相邻单元格的边框合并为一条线th用灰色背景加粗区分表头td居中对齐日期数字。关键知识点拆解为什么month要减 1JavaScript 的Date对象中月份是从0开始计数的0代表一月11代表十二月。因此当用户传入的month是「112」的自然月编号时必须执行mon month - 1再传给new Date(year, mon)。这是本任务最容易踩的第一个坑官方解答中专门用注释强调了这一点。关于Date对象的构造与常用方法可以复习教程 日期和时间Date 章节。为什么每周从星期一开始需要重写 getDay原生Date.prototype.getDay()返回0星期日到6星期六也就是一周从星期日开始。而本任务要求日历以星期一开始星期日在最后。官方的getDay(date)辅助函数完成了一次坐标转换function getDay(date) { // 从 0星期一到 6星期日 let day date.getDay(); if (day 0) day 7; // 星期日0变成 7即最后一天 return day - 1; // 整体左移一位 }转换结果星期一 →0星期二 →1……星期六 →5星期日 →6。这样一来月初第一天是星期几就决定了第一行前面要放几个空格单元格for (let i 0; i getDay(d); i)星期日的编号是6所以getDay(d) % 7 6可以判断「是否到了该换行的时候」。这里的% 7写法让判断在逻辑上更通用等价于getDay(d) 6。遍历整个月setDate 自增与 getMonth 边界判断生成日期单元格的核心是一个while循环while (d.getMonth() mon) { table td d.getDate() /td; if (getDay(d) % 7 6) { table /trtr; } d.setDate(d.getDate() 1); }d.setDate(d.getDate() 1)是 JavaScript 中「日期加一天」的标准写法。它的巧妙之处在于当日期越过当月边界时例如 9 月 30 日 1Date对象会自动进位到下个月的 1 号因此d.getMonth()会变成mon 1循环条件d.getMonth() mon自然失效循环随之终止——不需要手动计算每月有多少天。循环结束后d恰好指向下个月的 1 号此时getDay(d)的值恰好等于「本月最后一天之后剩余的空格数」因此最后一行补空格的逻辑可以直接复用if (getDay(d) ! 0) { for (let i getDay(d); i 7; i) { table td/td; } }这个设计非常精妙不需要额外保存任何状态循环退出时d本身携带的星期信息就足够补齐最后一行了。为什么用 innerHTML 而不是 DOM 方法逐个插入在 07-modifying-document/article.md 章节中你学到了多种插入节点的方法append、prepend、insertAdjacentHTML等。本任务选择innerHTML而非逐个createElementappend理由很实际代码量更少整张表格只需一条字符串拼接循环不需要为每个td单独创建节点结构一目了然字符串中的tr/td层级关系直接映射最终表格结构便于阅读和调试性能足够对一张月历这样的小型静态结构一次性赋值innerHTML比几十次 DOM 插入调用更高效。当然如果你希望代码风格更贴近「DOM 操作」教学点也可以用document.createElement(table)配合append逐行逐格构建两种方式都能通过本任务只是官方解答选择了更简洁的字符串方案。验证与运行方式仓库为本题提供了两个可直接运行的页面source.view/index.html任务起始模板函数体为空solution.view/index.html完整解答打开即可看到 2012 年 9 月的日历渲染结果。验证建议将createCalendar(calendar, 2012, 9)中的参数替换为其他年份/月份组合重点检查三类边界情况月初是星期日如 2012 年 1 月第一行不应出现空格单元格直接从 1 号开始月末不落在星期日如 2012 年 9 月之外的其他月份最后一行应有正确的空格补齐保证整张表格行数完整二月平年/闰年如 2011 年 2 月 28 天、2012 年 2 月 29 天验证while循环边界判断是否正确终止。总结「创建日历」是 DOM 修改章节的综合性练习它把三个关键能力串联在一起日期计算new Date(year, month - 1)处理月份偏移setDate(getDate() 1)自动跨月getMonth()判断月界星期坐标转换用getDay辅助函数把原生「星期日开头」的编号改造成「星期一开头」并据此计算行首空格与换行时机表格字符串生成用一条table.../table字符串配合innerHTML一次性写入兼顾简洁与性能。掌握这套模式后你可以轻松扩展出带周数、节假日高亮、前后月切换等交互功能的日历组件——但正如任务所说先让一张静态月历正确渲染出来是一切扩展的地基。赞分享文档教程前端【免费下载链接】zh.javascript.info现代 JavaScript 教程The Modern JavaScript Tutorial以最新的 ECMAScript 规范为基准通过简单但足够详细的内容为你讲解从基础到高阶的 JavaScript 相关知识。项目地址https://gitcode.com/gh_mirrors/zh/zh.javascript.info点击查看免费下载相关推荐使用 JavaScript 生成月份日历表格createCalendar 实战解析Modern JavaScript Tutorial使用 JavaScript 生成月份日历表格createCalendar 实战解析Modern JavaScript Tutorial 导读 本文围绕 M文档/教程前端JavaScript.info 实战用 innerHTML 与 Date 对象编写动态日历表格createCalendar 全解析JavaScript.info 实战用 innerHTML 与 Date 对象编写动态日历表格createCalendar 全解析 本篇文章基于《现代 J文档教程前端事件委托实战用 30 行代码实现可排序表格zh.javascript.info 教程任务解析事件委托实战用 30 行代码实现可排序表格zh.javascript.info 教程任务解析 导读 本文基于《现代 JavaScript 教程》zh.j文档教程前端上一篇ARIS 专利撰写系列USPTO 美国专利申请格式指南Claims / Specification / Drawings / IDS 全解析下一篇kkFileView CAD图纸参数提取技术架构与系统设计深度解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Haxe 跨平台工具包深度指南:语言、编译器、标准库与源码构建全解析

Haxe 跨平台工具包深度指南:语言、编译器、标准库与源码构建全解析

编程语言编译器语言运行时标准库 【免费下载链接】haxe Haxe - The Cross-Platform Toolkit 项目地址: https://gitcode.com/gh_mirrors/ha/haxe 点击查看 免费下载 Haxe 是一个开源跨平台开发工具包,其核心由一门现代强类型编程语言、一个面向多目标的…

2026/10/9 5:05:46 阅读更多 →
ai_quant_trade 债券大宗交易明细接入实战:Tushare bond_blk_detail 接口全解析

ai_quant_trade 债券大宗交易明细接入实战:Tushare bond_blk_detail 接口全解析

金融科技示例工程 【免费下载链接】ai_quant_trade Stock AI Trader: 1-stop platform for learning, sim & live trading. Covers: stock basics, strategies, LLMs, factor mining, ML/DL/RL, graph nets, HFT, C deploy & JoinQuant code. 股票AI操盘手:…

2026/10/8 1:33:32 阅读更多 →
TypeHero Advent of TypeScript 2023 Day 14「Naughty List Decipher」:用模板字面量类型递归实现字符串分割为联合类型

TypeHero Advent of TypeScript 2023 Day 14「Naughty List Decipher」:用模板字面量类型递归实现字符串分割为联合类型

教育前端后端 【免费下载链接】typehero Connect, collaborate, and grow with a community of TypeScript developers 项目地址: https://gitcode.com/gh_mirrors/ty/typehero 点击查看 免费下载 本文是 TypeHero Advent of TypeScript(AOT&#xff09…

2026/10/9 4:17:48 阅读更多 →

最新新闻

输电线路行波测距原理与Simulink仿真实战解析

输电线路行波测距原理与Simulink仿真实战解析

干了几年输电线路故障分析,我最头疼的一件事,就是线路跳闸之后要第一时间给调度报出故障点在哪。传统测距算法靠工频量硬算,遇到高阻接地、运行方式变化大的场景,误差几公里是家常便饭,现场巡线的人沿着线路找一整夜也…

2026/10/9 7:58:26 阅读更多 →
Deepseek生成Word/Excel文件全攻略:从复制粘贴到API自动化

Deepseek生成Word/Excel文件全攻略:从复制粘贴到API自动化

说实话,我第一次被问到“Deepseek能不能直接生成Word或Excel文件”的时候,也愣了一下。因为大多数人对大模型的预期,和它实际能做的事之间存在一道认知差——你让它“生成一个销售统计表.xlsx”,它回你一大段文字,你复…

2026/10/9 7:58:26 阅读更多 →
MCU晶振电路设计实战:匹配电容计算、PCB布局与起振排查

MCU晶振电路设计实战:匹配电容计算、PCB布局与起振排查

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 7:58:26 阅读更多 →
拓扑排序+关键路径(哈喜老师版本)

拓扑排序+关键路径(哈喜老师版本)

1.拓扑排序 1.1:拓扑排序的性质1.2:生成拓扑排序(2010年题8、2014年题7、2018年题7、2021年题7)1.3:例题1.4:结论 (2012年题6考了)2.关键路径 2.1:概念2.2:求关键路径需要用到的五个指标 a:事件…

2026/10/9 7:58:26 阅读更多 →
从“能用”到“无可挑剔”:一套提升交付完成度的方法论

从“能用”到“无可挑剔”:一套提升交付完成度的方法论

1. 一个词引发的思考:为什么“impeccable”值得单独拿出来聊第一次看到“impeccable”这个词被当成一个项目标题,我愣了一下。这词在英文里是“无可挑剔的、完美的”意思,词根来自拉丁语impeccabilis,im-(否定&#xf…

2026/10/9 7:58:26 阅读更多 →
用SRE思维学Linux:不背命令,掌握系统故障排查核心

用SRE思维学Linux:不背命令,掌握系统故障排查核心

说实话,我见过太多人学Linux,第一件事就是找一份“Linux常用命令大全”,背了100个命令,然后发现自己连一台出问题的机器都救不回来。2026年了,如果还在用背单词的方式学Linux,那基本是在做无用功。不是命令…

2026/10/9 7:57:26 阅读更多 →

日新闻

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API实战:LocalDate、Date与ZonedDateTime的转换与避坑指南

Java时间API这个话题,隔三差五就会在群里被翻出来讨论一次。上周还有个同事线上处理一个订单超时问题,排查到最后发现是ZonedDateTime序列化后时区丢了,用户在下单当天晚上看到的时间整整差了8个小时。这类问题几乎每个做Java开发的人都遇到过…

2026/10/9 0:00:49 阅读更多 →
EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

EasyTier实践:从NAT穿透到子网代理的异地组网部署与排错

前几个月我手头有好几台机器需要互相访问:办公室台式机、家里 NAS、还有一台云主机。如果只是偶尔传个文件倒还好,问题是工作场景经常要在几处环境之间来回切换,每次都先登录跳板机再层层代理,实在折腾。我先后试过端口映射、自建…

2026/10/9 0:00:49 阅读更多 →
AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent工程实战:从七要素到七个决策点的系统设计指南

AI Agent 这个词在过去一年里被反复提及,但真正动手搭过一套能跑起来的 Agent 系统的人都知道,从"知道它是什么"到"让它稳定干活"之间隔着一整套工程决策。我前后参与过几个 Agent 项目的落地,从最初用现成框架拼装&…

2026/10/9 0:01:50 阅读更多 →

周新闻

KT148A语音芯片外挂8002D功放的工程实践指南

KT148A语音芯片外挂8002D功放的工程实践指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:32 阅读更多 →
LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

LLC谐振变换器增益公式推导:从FHA等效到完整归一化表达式

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:40 阅读更多 →
ARM架构深度解析:从RISC设计理念到交叉编译实战

ARM架构深度解析:从RISC设计理念到交叉编译实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 10:10:36 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 21:13:17 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/8 15:26:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/9 6:17:20 阅读更多 →