Skip to content

1-14函数综合案例 ​

本页对应 第一章JavaScript基础,共 2 段视频,约 17 分钟。

学习目标 ​

  1. 能够使用 prompt 获取用户输入的总秒数,并通过 + 将其转换为数字型后保存到变量中。
  2. 能够封装并调用 getTime(t) 函数,将总秒数作为实参传入,并在函数形参中接收处理。
  3. 能够使用取整与取余公式将总秒数换算为小时、分钟、秒,并正确赋值给对应变量。
  4. 能够使用三元表达式对小时、分钟、秒进行小于 10 补零操作,输出两位数字格式。
  5. 能够通过 return 返回包含三个 span 标签的模板字符串,并将计算后的时分秒数据替换到对应位置。
  6. 能够将返回的带标签字符串渲染到页面指定容器中,并使用 61 秒、1000 秒等输入验证转换与显示结果。

知识点 ​

需求与效果 ​

综合案例效果图

为什么需要:学完函数后,需要用一个小案例把“输入、计算、封装、返回、渲染”串起来,避免只记住零散语法。
怎么想:用户输入总秒数,程序自动换算成“时、分、秒”,并显示成 00:01:01 这种两位数形式。
怎么做:先弹窗输入总秒数,再封装 getTime 计算时分秒并补 0,最后把结果写到页面盒子中。
易错点:prompt 得到的是字符串,参与计算前要转成数字;页面展示要补 0,否则 1 不如 01 整齐。

三步拆解 ​

为什么需要:案例虽小,但步骤不清就容易把“输入、计算、输出”混在一起。
怎么想:转写稿中明确分成三步:① 用户弹窗输入总秒数;② 封装 getTime,计算时分秒并补 0;③ 打印输出到页面。
怎么做:第一步用 let totalSeconds = +prompt('请您输入总的秒数:');第二步定义函数并调用;第三步用 document.write 输出盒子结构。
易错点:函数要先定义再调用;调用时小括号里写“实参”,定义时小括号里写“形参”。实参不一定是具体数字,也可以是变量,例如 getTime(totalSeconds)。

公式推导 ​

为什么需要:总秒数不能直接拆成时分秒,需要按 60 进制换算。
怎么想:秒数对 60 取余,剩下的就是“秒”;总秒数除以 60 得到总分钟,再对 60 取余,就是“分钟”;总秒数除以 60 再除以 60 得到总小时,对 24 取余得到一天内的小时。
怎么做:

  • 小时:h = parseInt(t / 60 / 60 % 24)
  • 分钟:m = parseInt(t / 60 % 60)
  • 秒数:s = parseInt(t % 60)
    易错点:parseInt 是取整,不是“pasin”;取余符号是 %,不是“余上”。例如输入 61 秒:61 % 60 = 1,所以秒是 1;parseInt(61 / 60 % 60) = 1,所以分钟是 1;小时是 0。调试时控制台输出 0 1 1,说明公式正确。

函数封装与补零 ​

为什么需要:计算逻辑要复用,且展示时间通常要求两位数。
怎么想:把总秒数作为形参 t 传进函数,先算出 h、m、s,再用三元表达式判断是否小于 10。
怎么做:

js
h = h < 10 ? '0' + h : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s

转写稿中验证:输入 61,补零前是 0 1 1,补零后控制台显示 00 01 01;输入 1000,可得到 0 16 40,即 16 分 40 秒。
易错点:补零后要重新赋值给 h/m/s,不能只写表达式;'0' 是字符串,拼接后变成字符串;函数内变量要写 let,否则直接赋值可能变成全局变量,很危险。变量查找遵循“先局部,局部没有再找全局”。

返回带标签字符串并渲染 ​

为什么需要:计算结果不仅要打印,还要放进页面的三个 span 中。
怎么想:让 getTime 返回一段带标签的字符串,里面用模板字符串填入真实数据;外部用变量接住返回值,再塞进 .timer 盒子。
怎么做:函数中返回:

js
return `
  <span class="hour">${h}</span>
  <span class="minute">${m}</span>
  <span class="second">${s}</span>
`

调用 let str = getTime(totalSeconds),最后在 document.write 的模板字符串中把原来的三个 span 删掉,换成 \${str}。
易错点:return 返回的是“带标签的字符串”,不是数字;模板字符串要用反引号;\${str} 不要写成普通字符串拼接;页面输出时盒子外壳保留,三个 span 用返回值替换。

完整代码 ​

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>综合案例-转换时间案例</title>
  <style>
    .box {
      position: relative;
      width: 190px;
      height: 260px;
      color: #fff;
      background: #e83632 url(./images/bg.png) 50%/contain no-repeat;
    }

    .title {
      width: 100%;
      text-align: center;
      font-size: 30px;
      font-weight: 700;
      padding-top: 31px;
    }

    .count {
      margin-top: 90px;
      font-size: 14px;
      text-align: center;
    }

    .timer {
      margin-left: auto;
      margin-right: auto;
      width: 130px;
      height: 30px;
      margin-top: 10px;
      display: block;
    }

    .timer span {
      position: relative;
      float: left;
      width: 30px;
      height: 30px;
      text-align: center;
      background-color: #2f3430;
      margin-right: 20px;
      color: white;
      font-size: 20px;
    }

    .timer span:nth-child(-n+2)::after {
      content: ":";
      display: block;
      position: absolute;
      right: -20px;
      font-weight: bolder;
      font-size: 18px;
      width: 20px;
      height: 100%;
      top: 0;
    }

    .timer span:last-child {
      margin-right: 0;
    }
  </style>
</head>

<body>
  <!-- <div class="box">
    <div class="title">计算时间</div>
`<div>`
      <div class="count">转换为时分秒</div>
      <div class="timer">
        <span class="hour">01</span>
        <span class="minute">22</span>
        <span class="second">58</span>
      </div>
    </div>
  </div> -->

  <script>
    // 转换时分秒案例 
    // 计算公式:计算时分秒
    // 小时:  h = parseInt(总秒数 / 60 / 60 % 24)
    // 分钟:  m = parseInt(总秒数 / 60 % 60)
    // 秒数:   s = parseInt(总秒数 % 60) 

    // 1. 用户输入总的秒数
    let totalSeconds = +prompt('请您输入总的秒数:')

    // 2. 封装函数 getTime,把总的秒数转换为时分秒,注意记得数字补0 哦
    function getTime(t = 0) {
      // 转换小时
      let h = parseInt(t / 60 / 60 % 24)
      // 转换分钟
      let m = parseInt(t / 60 % 60)
      // 转换秒数
      let s = parseInt(t % 60)
      // 数字补0
      h = h < 10 ? '0' + h : h
      m = m < 10 ? '0' + m : m
      s = s < 10 ? '0' + s : s
      console.log(h, m, s)
      return `
        <span class="hour">\${h}</span>
        <span class="minute">\${m}</span>
        <span class="second">\${s}</span>
      `
    }
    let str = getTime(totalSeconds) // 实参
    console.log(str)
    // 3. 页面打印输出
    document.write(`
       <div class="box">
        <div class="title">计算时间</div>
`<div>`
          <div class="count">转换为时分秒</div>
          <div class="timer">
            \${str}
          </div>
        </div>
      </div>
    `)
  </script>
</body>

</html>

课件图示 ​

课件第4页:函数-Function 函数: 是可以被重复使用的代码块 作用:函数可以把具有相

课件第6页:函数基本使用 定义一个函数并不会自动执行它,需要调用函数 2. 调用函数 利用关

课件第7页:总结 总结 1. 函数是什么?有什么好处? Ø 可以被重复使用的代码块 Ø 代码

课件第11页:1.2 函数整体认知 问题:这样的函数只能求 10 + 20, 而且结果只能函数

课件第12页:1.2 函数整体认知 l 函数语法 l 说明: Ø 函数参数,如果有多个则用逗号

课件第15页:1.3 函数参数 Ø 形参:声明函数时小括号里的叫形参(形式上的参数) Ø 实参

课件第17页:总结 总结 1. 函数中实参在哪里?形参在哪里? Ø 函数调用时,小括号里面的是

课件第18页:逻辑中断 逻辑中断: 存在于逻辑运算符 && 和 || 中,左边如果满足一定条件

代码示例 ​

代码一:综合案例完整代码(HTML + CSS + JS) ​

js
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>综合案例-转换时间案例</title>
  <style>
    .box {
      position: relative;
      width: 190px;
      height: 260px;
      color: #fff;
      background: #e83632 url(./images/bg.png) 50%/contain no-repeat;
    }

    .title {
      width: 100%;
      text-align: center;
      font-size: 30px;
      font-weight: 700;
      padding-top: 31px;
    }

    .count {
      margin-top: 90px;
      font-size: 14px;
      text-align: center;
    }

    .timer {
      margin-left: auto;
      margin-right: auto;
      width: 130px;
      height: 30px;
      margin-top: 10px;
      display: block;
    }

    .timer span {
      position: relative;
      float: left;
      width: 30px;
      height: 30px;
      text-align: center;
      background-color: #2f3430;
      margin-right: 20px;
      color: white;
      font-size: 20px;
    }

    .timer span:nth-child(-n+2)::after {
      content: ":";
      display: block;
      position: absolute;
      right: -20px;
      font-weight: bolder;
      font-size: 18px;
      width: 20px;
      height: 100%;
      top: 0;
    }

    .timer span:last-child {
      margin-right: 0;
    }
  </style>
</head>

<body>
  <script>
    // 转换时分秒案例
    // 计算公式:计算时分秒
    // 小时:  h = parseInt(总秒数 / 60 / 60 % 24)
    // 分钟:  m = parseInt(总秒数 / 60 % 60)
    // 秒数:   s = parseInt(总秒数 % 60)

    // 1. 用户输入总的秒数
    let totalSeconds = +prompt('请您输入总的秒数:')

    // 2. 封装函数 getTime,把总的秒数转换为时分秒,注意记得数字补0 哦
    function getTime(t = 0) {
      // 转换小时
      let h = parseInt(t / 60 / 60 % 24)
      // 转换分钟
      let m = parseInt(t / 60 % 60)
      // 转换秒数
      let s = parseInt(t % 60)
      // 数字补0
      h = h < 10 ? '0' + h : h
      m = m < 10 ? '0' + m : m
      s = s < 10 ? '0' + s : s
      console.log(h, m, s)
      return `
        <span class="hour">${h}</span>
        <span class="minute">${m}</span>
        <span class="second">${s}</span>
      `
    }
    let str = getTime(totalSeconds) // 实参
    console.log(str)
    // 3. 页面打印输出
    document.write(`
       <div class="box">
        <div class="title">计算时间</div>
        <div>
          <div class="count">转换为时分秒</div>
          <div class="timer">
            ${str}
          </div>
        </div>
      </div>
    `)
  </script>
</body>

</html>

关键行与易错点

  • let totalSeconds = +prompt('请您输入总的秒数:'):prompt 拿到的是字符串,前面必须加 + 转成数字型,否则后面做除法会得到 NaN。
  • 三个公式直接照抄:h = parseInt(t / 60 / 60 % 24)、m = parseInt(t / 60 % 60)、s = parseInt(t % 60)。parseInt 用来取整(时间是整数),% 24 保证小时不超过 24。验证:61 秒 → 0 时 1 分 1 秒;1000 秒 → 16 分 40 秒。
  • 补 0 写法:h = h < 10 ? '0' + h : h。注意 '0' 必须加引号,写成 0 + h 就变成数字相加(0 + 1 = 1,得不到 01);另外结果要重新赋值回 h,只写表达式不赋值等于白做。
  • 形参写成 t = 0 是给默认值,防止调用时不传参变成 undefined 而算出 NaN。
  • 函数内 let h、let m、let s 三个 let 一个都不能漏,漏了就成了隐式全局变量,后面很容易被覆盖。
  • return 返回的是带标签的模板字符串(用反引号),里面用 \${h} 把算好的真实数据嵌进去。
  • document.write 里的 .timer 盒子不再写死三个 span,只用 \${str} 把函数返回的字符串塞进去即可,这是本案例最核心的思路。
  • 样式里的 url(./images/bg.png) 需要本地有这张图,没有图片时代码照样能运行,只是背景色为纯红。

代码二:分步验证——先算时分秒,再做数字补 0 ​

html
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>分步验证-转换与补0</title>
</head>

<body>
  <script>
    // 1. 用户输入总的秒数(别忘了转数字型)
    let totalSeconds = +prompt('请您输入总的秒数:')

    // 2. 封装函数 getTime,把总的秒数转换为时分秒
    function getTime(t = 0) {
      // 转换小时
      let h = parseInt(t / 60 / 60 % 24)
      // 转换分钟
      let m = parseInt(t / 60 % 60)
      // 转换秒数
      let s = parseInt(t % 60)

      // 数字补0
      h = h < 10 ? '0' + h : h
      m = m < 10 ? '0' + m : m
      s = s < 10 ? '0' + s : s

      console.log(h, m, s)
    }

    // 3. 调用函数,把变量当实参传进去
    getTime(totalSeconds)
  </script>
</body>

</html>

关键行与易错点

  • 这一步只做到"控制台验证",先确认计算和补 0 都对,再去渲染页面,排错会轻松很多。
  • 调用 getTime(totalSeconds):小括号里是实参,实参不一定是写死的数字,放变量完全可以,变量里存的就是用户输入的秒数。
  • 形参 t 把实参接过来,后面所有公式里都用 t 参与计算,不要再写成别的变量名。
  • 补 0 三行是最容易出错的地方:'0' + h 是字符串拼接,h 必须是重新赋值,写成 h < 10 ? '0' + h : h 而不管它,打印出来还是 0 不是 00。
  • 输入 61,控制台应输出 00 01 01;输入 1000,应输出 00 16 40。

代码三:函数 return 带标签的字符串,再渲染到页面 ​

js
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>返回字符串并渲染</title>
</head>

<body>
  <script>
    // 1. 用户输入总的秒数
    let totalSeconds = +prompt('请您输入总的秒数:')

    // 2. 封装函数 getTime:计算 + 补0 + 返回带标签的字符串
    function getTime(t = 0) {
      let h = parseInt(t / 60 / 60 % 24)
      let m = parseInt(t / 60 % 60)
      let s = parseInt(t % 60)

      h = h < 10 ? '0' + h : h
      m = m < 10 ? '0' + m : m
      s = s < 10 ? '0' + s : s

      return `
        <span class="hour">${h}</span>
        <span class="minute">${m}</span>
        <span class="second">${s}</span>
      `
    }

    // 3. 用变量接住返回值,再打印到页面
    let str = getTime(totalSeconds)
    console.log(str)

    document.write(`
      <div class="timer">
        ${str}
      </div>
    `)
  </script>
</body>

</html>

关键行与易错点

  • return 后面返回的不是数字,而是一段带标签的字符串,模板字符串必须用反引号包裹,\${h} 会被替换成真实数据。
  • let str = getTime(totalSeconds):调用一次函数就执行一遍,并把 return 的结果装进 str,此时 str 里已经是"三个带真实数据的 span"。
  • document.write 里的 .timer 只写外壳,用 \${str} 插入三个 span,所以原来素材里写死的 01 / 22 / 58 要删掉。
  • 常见坑:在模板字符串里写了 \${h} 但 h 是函数内部的局部变量,函数外拿不到——必须先 return 出来再使用。
  • 如果这段代码单独运行,因为没有引入代码一里的 CSS,.timer span 的方块样式不会出现,只是纯文本数字,但结构和数据是正确的;把 <style> 拷过来即可看到完整效果。

常见错误 ​

1. 补零失效,输出 0 1 1 而不是 00 01 01

  • 现象:小时/分钟/秒小于 10 时,前面没有出现 0。
  • 原因:写成了 h = h < 10 ? 0 + h : h,0 + 5 是数值加法得 5,不是字符串拼接;或者写成 h += '0' 把零加在了后面。
  • 修法:'0' 必须带引号且放在前面 —— h = h < 10 ? '0' + h : h,并且要把结果重新赋值回 h。

2. 函数返回 undefined,页面 timer 里出现 undefined

  • 现象:let str = getTime(totalSeconds) 后打印 str 是 undefined,页面渲染空白或报错。
  • 原因:函数体内只写了 console.log(h, m, s) 而没有 return;或 return 写在模板字符串之前/之后位置不对,执行不到。
  • 修法:把带三个 span 的模板字符串用 return 返回,console.log 只用于调试,不承担输出职责。

3. 输入 90000 秒,小时却显示 01

  • 现象:秒数很大时小时数被"截断",看起来像丢数据。
  • 原因:公式里的 % 24 是取"一天内的第几小时",超过 24 小时的部分被主动丢弃。
  • 修法:确认需求 —— 要"24 小时制显示"就保留 % 24;要显示累计小时数就去掉 % 24,只写 parseInt(t / 3600)。

4. 形参名和函数体里用的变量名不一致,结果全是 NaN / undefined

  • 现象:getTime(totalSeconds) 调用正常,但函数里算出来的 h、m、s 都是 NaN。
  • 原因:形参写的是 t,函数体里却继续写 totalSeconds;此时函数内找不到该变量,会沿着作用域链去全局找,全局也没有就是 undefined,参与运算即 NaN。
  • 修法:形参名与函数体内引用的名字严格保持一致;这类错误不报错、只出错值,写完先 console.log(t) 确认接到了。

5. 输入非数字或点"取消",页面显示 NaN:NaN:NaN

  • 现象:prompt 直接取消或输入字母,三个 span 里全是 NaN。
  • 原因:+prompt(...) 对 null 或非数字字符串转换结果是 NaN,NaN 参与任何算术运算仍是 NaN,补零判断 NaN < 10 为 false 所以连 0 都不补。
  • 修法:转换后先做校验,if (isNaN(totalSeconds)) { ... } 给出默认值或提示后终止,把非法输入挡在计算之前。

6. 页面样式全丢 / 结构错乱

  • 现象:数字出来了,但没有红底黑块的效果,或三个方块挤在一起没有冒号。
  • 原因:document.write 里拼的 HTML 少了 .box 或 .timer 外层容器;或 span 的 class 名拼错(hour / minute / second 与 CSS 选择器不一致),CSS 里 .timer span:nth-child(-n+2)::after 的冒号依赖结构层级。
  • 修法:渲染前把静态 HTML 结构和最终输出逐层比对,class 名一字不差;调试时可先只 document.write(str) 看片段是否正确。

练习 ​

练习 1(验证公式) 不写代码,先手算下列输入的结果并写出预期输出,再运行案例核对:61、3599、3600、86399、86400、90061。对不上的一项,指出是公式哪一部分造成的。

练习 2(改造需求) 把案例改成"累计时长"模式:输入 90000 秒应显示 25:00:00 而不是 01:00:00。只改一处代码实现,并说明改动后哪些输入的结果会与原来不同。

练习 3(拆分职责) 把 getTime 的返回值从 HTML 字符串改为数组 [h, m, s],由调用方负责拼三个 span 并 document.write。改造完成后对比两种写法:哪种更容易复用到"倒计时"场景?写出你的理由。

练习 4(复用扩展) 基于改造后的 getTime,做一个倒计时:输入总秒数后页面每秒刷新一次数字,减到 00:00:00 自动停止(提示:setInterval + 一个外部变量保存剩余秒数 + clearInterval)。要求倒计时过程中数字始终补零。

练习 5(健壮性) 为案例加上输入防护:用户取消 prompt、输入空字符串、输入负数、输入 abc 时,页面都应正常渲染 00:00:00 并给出提示,而不是出现 NaN 或报错。写出你的判断逻辑,并列出你测试过的边界用例清单。

原视频对照 ​

#视频时长
1综合案例-转换时分秒上10:48
2综合案例-转换时分秒下07:09

小结 ​

  1. 这个案例真正的难点不在换算公式,而在"数据 → 字符串 → 页面"这条链路的职责划分:函数只负责算和拼,调用方只负责接住和放入容器。
  2. 实参可以是变量而非字面量;形参一旦命名,函数体内必须使用同一个名字 —— 名字不一致不会报错,只会静默地拿到 undefined 并污染全部计算结果。
  3. 补零的本质是三目运算加字符串拼接,'0' 带不带引号决定了是"补零"还是"加零",这是本案例最高频的一处翻车点。
  4. return 决定了函数的产出形态;返回"带标签的字符串"是模板渲染的最小雏形,后续组件化、列表渲染都是这个思路的放大版。
  5. 函数内变量必须 let 声明,漏写会变成隐式全局变量,函数调用两次以上就可能互相污染 —— 这类 bug 在单次运行时完全看不出来。
  6. 边界输入(0、负数、null、非数字、超过 24 小时、正好 86400)是换算类需求的第一批测试用例,应在写代码前就想清楚期望行为,而不是等页面出 NaN 再补判断。
  7. 调试节奏上,"先验证 h/m/s → 再验证返回字符串 → 最后验证页面渲染"的分段验证,比一次性写完再看效果要快得多。