Skip to content

1-12函数及应用(一) ​

本页对应 第一章JavaScript基础,共 7 段视频,约 1 小时 8 分。

学习目标 ​

  • 能使用 function 关键字声明函数,并通过“函数名()”调用,说明函数不调用不执行、每次调用都会重新执行函数体。
  • 能将重复逻辑(如九九乘法表、1~100累加求和)封装为函数,并说明函数复用与 for 循环在执行时机上的区别。
  • 能编写带形参和 return 的函数,调用时传入实参并接收返回值,区分形参与实参,并判断参数个数不匹配时的执行结果。
  • 能利用逻辑与、逻辑或的中断规则改写求和函数,使未传参或传入 undefined 时返回 0,并解释短路执行过程。
  • 能为形参设置默认参数,说明默认值生效条件(未传实参或实参为 undefined),并比较默认参数与逻辑中断的适用场景。
  • 能封装并调用“秒数转换为时、分、秒”的函数,验证输入秒数后输出正确结果。

知识点 ​

函数是什么:先封装再复用 ​

为什么需要:页面不同位置要多次打印同一段逻辑时,复制代码既啰嗦又难维护。函数把“相同或相似逻辑”包起来,需要时调用一次即可,核心价值是代码复用。
怎么想:函数是可被重复使用的代码块,可以理解成一个“盒子”,把代码封装进去;定义只是准备盒子,调用才真正执行。
怎么做:用 function 声明函数,函数名后加 () 调用。

javascript
function sayHi() {
  console.log('嗨~')
}
sayHi()
sayHi()

调试时先只写定义,页面不会输出;补上 sayHi() 后才执行,说明“声明不执行,调用才执行”。
易错点:函数名与变量命名一致,采用小驼峰,常用动词;循环写完刷新就执行,函数则要等到调用时才执行,执行时机不同。

完整函数:参数、返回值与整体认知 ​

为什么需要:只写 sum 求固定 10+20 不灵活,结果还在函数内部打印,外部拿不到。完整函数应能接收数据、处理数据、返回结果。
怎么想:像榨汁机:调用者放“原料”(实参),函数用“形参”接收,内部处理后用 return 把结果返回给调用者。
怎么做:
函数整体认知

javascript
function sum(x, y) {
  return x + y
}
console.log(sum(1, 2)) // 3

返回值细节:return 会立即结束函数,后面代码不执行;return 与被返回表达式不要换行;没有 return 时默认返回 undefined。
易错点:return 后写代码不会执行;return 后换行可能被自动补分号;无返回值不要误以为返回 0。

形参和实参:个数不匹配怎么推 ​

为什么需要:函数要灵活,就要把调用时的数据传进去。声明函数时小括号里是形参,调用时小括号里是实参。
怎么想:传参过程类似赋值,sum(1,2) 可理解为 x=1、y=2;形参可当作变量理解。
怎么做:
形参和实参

javascript
function sum(x, y) {
  return x + y
}
console.log(sum(1, 2)) // 3
console.log(sum(1))    // NaN
console.log(sum(1, 2, 3)) // 3

推导:sum(1) 时 x=1,y 没接到值,默认是 undefined,所以 1 + undefined 得 NaN;实参多余时,多出的会被忽略。
易错点:形参过多自动补 undefined,实参过多多余忽略;开发中提倡实参与形参个数统一;形参可看作局部变量。

逻辑中断与默认参数:让缺参更严谨 ​

为什么需要:sum() 不传参会得到 NaN,但更合理的是返回 0,像查银行卡余额没金额也显示 0。
怎么想:逻辑与 && 左边为假就中断;逻辑或 || 左边为真就中断。可用 x = x || 0 兜底。
怎么做:

javascript
function sum(x, y) {
  x = x || 0
  y = y || 0
  return x + y
}
console.log(sum()) // 0
console.log(sum(1, 2)) // 3

默认参数更简单:function sum(x = 0, y = 0) { return x + y }。默认值只在没有实参或实参为 undefined 时生效。
易错点:默认参数主要处理形参;逻辑中断还能处理其他取值场景,二者不是谁替代谁。

作用域与匿名函数:变量边界和函数表达式 ​

为什么需要:变量需要有可用范围,减少命名冲突;匿名函数没有名字,不能直接调用,需要赋值给变量或立即执行。
怎么想:全局作用域作用于整个 script 或独立 js 文件;局部作用域包括函数作用域和块级作用域;访问变量遵循“就近原则”。
怎么做:函数表达式先定义后使用;IIFE 用于避免全局变量污染,多个立即执行函数要用 ; 隔开。

javascript
let fn = function() {
  console.log('函数表达式')
}
fn()

(function(){ /* ... */ })();
(function(){ /* ... */ }());

易错点:函数内变量未声明直接赋值会变成全局变量,强烈不推荐;形参可看作局部变量;函数表达式必须先定义后使用。

需求与效果:先把“秒数”变成看得懂的时分秒 ​

综合案例效果图

为什么需要:用户输入的是“总秒数”,但页面要展示的是“小时、分钟、秒”。如果直接把 10000 秒显示出来,阅读成本高;转换成 02:46:40 更直观。转写稿中也明确说,这个案例是在为后面的倒计时效果做铺垫。

怎么想:整个流程分三步:先弹窗拿到总秒数;再把总秒数交给函数计算时、分、秒并补 0;最后把结果拼接成 HTML 输出到页面。

怎么做:用 prompt 获取输入,用 +prompt(...) 转成数字;封装 getTime;用 document.write 输出页面结构。

易错点:prompt 默认返回字符串,虽然参与除法时常会隐式转换,但建议主动用 + 转数字;不要把“补 0 后的字符串”再拿去做数学计算。

计算公式:为什么是 /60/60%24、/60%60、%60 ​

为什么需要:时间换算是 60 进制,不是 10 进制。总秒数要先除以 60 得到分钟,再除以 60 得到小时;余数才是剩下的分钟和秒。

怎么想:以转写稿中的例子“10000 秒”推导:

  • 小时:parseInt(10000 / 60 / 60 % 24)
    10000/60/60 ≈ 2.777,%24 后仍取 2,结果是 2。
  • 分钟:parseInt(10000 / 60 % 60)
    10000/60 ≈ 166.66,166.66 % 60 ≈ 46.66,取整为 46。
  • 秒数:parseInt(10000 % 60)
    10000 % 60 = 40。

所以 10000 秒对应 2 小时 46 分 40 秒,和转写稿演示一致。

怎么做:在函数内分别写 h、m、s 三个变量,用 parseInt 取整。

易错点:小时公式里有 %24,表示按 24 小时循环显示;如果需求是“累计小时”而不是“当天小时”,就不能盲目 %24。本案例按笔记公式保留 %24。

函数封装与补 0:把重复逻辑装进“盒子” ​

为什么需要:计算和补 0 是一段完整逻辑,封装成函数后结构更清楚,也方便以后复用。转写稿中反复强调:函数是把代码“包裹/封装”起来,定义后不会自动执行,必须调用。

怎么想:先算数字,再补 0,最后返回 HTML 字符串。补 0 的判断是“小于 10 就在前面拼一个 '0'”。

怎么做:

js
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>。注意笔记代码中形参写了默认值 t = 0,未传参时也有兜底值。

易错点:补 0 后 h/m/s 可能变成字符串,不要再拿它们做加减;返回的是 HTML 字符串,不是数字;模板字符串要用反引号,变量用 ${}。

页面输出与调试:先看控制台,再写页面 ​

为什么需要:如果一上来就拼 HTML,出错时不容易判断是计算错了,还是结构写错了。

怎么想:先验证 getTime(totalSeconds) 返回的字符串是否正确,再把它插入 .timer 容器。

怎么做:笔记中先用 let str = getTime(totalSeconds) 接收返回值,console.log(str) 查看;然后用 document.write 输出完整 .box 结构,把 \${str} 放进 .timer 中。

易错点:document.write 在页面加载阶段执行没问题,但在页面加载完成后调用可能覆盖原文档;本案例是加载时执行,按笔记写法即可。还要注意 HTML 中的类名 hour/minute/second 与 CSS 对应。

完整代码 ​

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>
  <!-- <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. 函数中实参在哪里?形参在哪里? Ø 函数调用时,小括号里面的是

课件第19页:1.3 函数参数 - 默认参数 默认参数:可以给形参设置默认值 说明:这个默认值

代码示例 ​

示例一:函数声明与调用、参数与返回值 ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JavaScript 基础 - 声明和调用</title>
</head>
<body>
  <script>
    // 函数:是可以被重复使用的代码块,作用是有利于代码复用
    // 1. 声明(定义)了最简单的函数,既没有形式参数,也没有返回值
    function sayHi() {
      console.log('嗨~')
    }

    // 函数调用,这些函数体内的代码逻辑会被执行
    // 函数名()
    sayHi()
    // 可以重复被调用,多少次都可以
    sayHi()

    // 2. 完整函数:参数 + 返回值
    function sum(x, y) {   // x、y 是形参
      return x + y
    }
    console.log(sum(1, 2))     // 3
    console.log(sum(1))        // NaN   1 + undefined
    console.log(sum(1, 2, 3))  // 3     多余的实参会被忽略

    // 3. return 细节:没有 return 默认返回 undefined
    function fn() {}
    console.log(fn())          // undefined
  </script>
</body>
</html>

要点:

  • function 声明函数,函数名采用小驼峰、尽量用动词;声明好的函数不会自动执行,必须 函数名() 调用。
  • 形参(声明时)本质就是变量,实参(调用时)的值会依次赋给形参;形参多则自动补 undefined,实参多则被忽略,开发中提倡个数统一。
  • return 会立即结束函数,后面的代码不执行;return 和被返回的表达式之间不能换行,否则自动补分号等于返回 undefined。

示例二:逻辑中断与默认参数 ​

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>逻辑中断与默认参数</title>
</head>
<body>
  <script>
    // 1. 逻辑与中断:左边为假则中断并返回左边的值;左边为真则返回右边的值
    console.log(false && 1 + 2)      // false
    console.log(0 && 1 + 2)          // 0
    console.log('' && 1 + 2)         // ''
    console.log(undefined && 1 + 2)  // undefined
    console.log(true && 1 + 2)       // 3   此处不会发生逻辑中断
    console.log(1 && 1 + 2)          // 3   此处不会发生逻辑中断

    // 2. 逻辑或中断:左边为真则中断并返回左边的值;左边为假则返回右边的值
    console.log(true || 1 + 2)       // true  发生了中断
    console.log(1 || 1 + 2)          // 1     发生了中断
    console.log(false || 1 + 2)      // 3     此处不会发生逻辑中断

    // 3. 使用场景一:用逻辑或中断让求和函数更严谨
    function sum1(x, y) {
      x = x || 0
      y = y || 0
      return x + y
    }
    console.log(sum1())      // 0
    console.log(sum1(1, 2))  // 3

    // 4. 使用场景二:默认参数,写法更简单
    function sum2(x = 0, y = 0) {
      return x + y
    }
    console.log(sum2())                     // 0
    console.log(sum2(undefined, undefined)) // 0
    console.log(sum2(1, 2))                 // 3
  </script>
</body>
</html>

要点:

  • 逻辑中断(逻辑短路)只存在于 && 和 || 中;为假的 6 种情况:false、0、''、null、undefined、NaN,其余都为真。
  • x = x || 0:有实参时左边为真直接中断、原值保留;无实参时左边为 undefined(假),取右边的 0,从而避免 undefined + undefined = NaN。
  • 默认参数 x = 0 只在没有实参传递、或传递的是 undefined 时才执行;传了具体值就优先用实参。
  • 两者区别:处理形参用默认参数更简单;逻辑中断除了参数还能做别的取值兜底(如获取不到值就用 1)。

示例三:综合案例——秒数转换为时分秒 ​

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>

要点:

  • prompt 返回的是字符串,前面加 + 转成数字,否则 /、% 运算结果会出错。
  • parseInt 取整;小时用 % 24 保证不超过 24 小时;t = 0 是默认参数,防止没有传入秒数时算出 NaN。
  • 补 0 用三元表达式 h < 10 ? '0' + h : h,注意要把结果重新赋值回变量,只写表达式不赋值等于没补。
  • 函数内部用 return 把拼接好的模板字符串交给调用者,由外部 document.write 渲染,体现“封装 + 返回值”的配合;.box 的背景图 ./images/bg.png 需存在对应图片,缺失不影响结构显示。

常见错误 ​

  1. 现象:页面没有任何输出,误以为函数写错 → 原因:只声明了函数,没有调用 → 修法:声明后按需写 函数名() 调用,并检查调用语句是否执行到。
  2. 现象:函数明明计算了,外部却拿到 undefined → 原因:return 后换行,或函数根本没有 return → 修法:return 与返回表达式写在同一行;需要结果时显式返回。
  3. 现象:sum(1) 得到 NaN,sum(1,2,3) 结果与预期不一致 → 原因:形参与实参数量不匹配 → 修法:调用与定义保持数量一致;入口处用默认参数或兜底逻辑处理缺省值。
  4. 现象:函数表达式在定义前调用直接报错 → 原因:函数表达式本质是赋值,必须先定义后使用 → 修法:先写 let fn = function(){},再调用 fn()。
  5. 现象:连续写多个立即执行函数时报错 → 原因:多个 IIFE 之间缺少分隔 → 修法:每个 IIFE 后补分号,或使用前置分号分隔。
  6. 现象:函数内部变量跑到全局,造成命名污染 → 原因:变量未声明就直接赋值 → 修法:局部变量显式声明,形参按局部变量使用。
  7. 现象:传入 0 或空字符串时被默认值替换 → 原因:误把逻辑或兜底当成默认参数使用 → 修法:参数缺省优先用默认参数;需要兜底时先确认业务是否允许 0、'' 等假值。

练习 ​

  1. 封装 getSum(x, y = 0) 返回两数之和,分别调用 getSum()、getSum(5)、getSum(1, 2),写出结果并说明原因。
  2. 封装 getTime(totalSeconds = 0),返回 HH:MM:SS 字符串,要求时分秒不足两位补 0,并分别测试不传参、传 10000。
  3. 写出下列输出:console.log(0 || 5)、console.log(5 || 0)、console.log(0 && 5)、console.log(5 && 0)。
  4. 用函数表达式封装“求 1 到 n 的累加和”,n 默认 100,先定义后调用,分别测试 sum(10) 和不传参调用。
  5. 用两个 IIFE 分别输出当前小时和分钟(不足两位补 0),要求连续书写不报错,并避免全局变量污染。

原视频对照 ​

#视频时长
1今日内容01:12
2函数的基本使用13:55
3函数封装小练习04:46
4函数的整体认知12:53
5函数参数10:01
6逻辑中断16:11
7默认参数09:41

小结 ​

  1. 函数的核心价值是封装与复用,声明不等于执行,调用才会执行。
  2. 完整函数要关注入参、内部处理、返回值三个环节,调用者通过返回值获取结果。
  3. 参数数量可以不一致,但开发中应尽量统一;默认参数只处理缺省或 undefined。
  4. return 会立即结束函数,返回表达式不要换行;没有 return 时结果为 undefined。
  5. 作用域访问遵循就近原则,局部变量应显式声明,避免意外污染全局。
  6. 匿名函数常用于函数表达式和 IIFE;函数表达式先定义后调用,多个 IIFE 要用分号分隔。
  7. 逻辑中断适合做取值兜底,但要注意 0、空字符串等合法假值场景。
  8. 时间转换类案例应先计算、再补零、最后返回,避免在函数内部直接输出而降低复用性。