js基础

### 循环语句 使用场景:重复执行 指定的一段代码,比如我们想要输出10次 '我学的很棒' 学习路径: 1.while循环 2.for 循环(重点) #### while循环 while : 在…. 期间, 所以 while循环 就是在满足条件期间,重复执行某些代码。 **语法:** ~~~javascript while (条件表达式) { // 循环体 } ~~~ 例如: ~~~javascript // while循环: 重复执行代码 // 1. 需求: 利用循环重复打印3次 '月薪过万不是梦,毕业时候见英雄' let i = 1 while (i <= 3) { document.write('月薪过万不是梦,毕业时候见英雄~<br>') i++ // 这里千万不要忘了变量自增否则造成死循环 } ~~~ 循环三要素: 1.初始值 (经常用变量) 2.循环条件 3.变量计数(常用自增或者自减) #### for 循环 作用:重复执行指定的一段代码 好处:把声明初始值、循环条件、变量计数写到一起,让人一目了然,它是最常使用的循环形式 **语法:** ~~~javascript for (初始值; 循环条件; 变量计数) { // 满足条件执行的循环体 } ~~~ 例如: ~~~javascript // for循环:重复执行一段代码 // 1. 语法 // for(初始值; 循环条件; 变量计数) { // // 循环体 // } // 2. 需求: 重复打印3次 // '月薪过万不是梦,毕业时候见英雄。键盘敲烂要行动,前端行业一览众' for (let i = 1; i <= 3; i++) { document.write('键盘敲烂要行动,前端行业一览众~ <br>') } ~~~ #### 中止循环 `break` 中止整个循环,一般用于结果已经得到, 后续的循环不需要的时候可以使用(提高效率) `continue` 中止本次循环,一般用于排除或者跳过某一个选项的时候 ~~~javascript // 1.break中止整个for循环,一般用于结果已经得到, 后续的循环不需要的时候可以使用 // for (let i = 1; i <= 6; i++) { // document.write(`我是第${i}个孩子 <br>`) // if (i === 3) { // break // } // } // 2.continue中止本次循环,一般用于排除或者跳过某一个选项的时候 for (let i = 1; i <= 6; i++) { // 先验票,再进入电影院 if (i === 3) { continue } document.write(`第${i}个孩子可以进入电影院<br>`) } ~~~ #### 无限循环 1.while(true) 来构造“无限”循环,需要使用break退出循环。(常用) 2.for(;;)也可以来构造“无限”循环,同样需要使用break退出循环。 ~~~javascript // 无限循环 // 需求: 页面会一直弹窗询问你爱我吗? // (1). 如果用户输入的是 '爱',则退出弹窗 // (2). 否则一直弹窗询问 // 1. while(true) 无限循环 while (true) { let love = prompt('你爱我吗?') if (love === '爱') { break } } // 2. for(;;) 无限循环 for (; ;) { let love = prompt('你爱我吗?') if (love === '爱') { break } } ~~~ ## 综合案例-ATM存取款机 ![image.png](https://cos.easydoc.net/84678576/files/lu9xzw1m.png)! 分析: ①:提示输入框写到循环里面(无限循环) ②:用户输入4则退出循环 break ③:提前准备一个金额预先存储一个数额 money ④:根据输入不同的值,做不同的操作 ​ (1) 取钱则是减法操作, 存钱则是加法操作,查看余额则是直接显示金额 ​ (2) 可以使用 if else if 多分支 来执行不同的操作 完整代码: ~~~javascript // 综合案例 - ATM存取款机 // 提前声明金额变量 money let money = 100 // 1.提示输入框写到循环里面(无限循环) while (true) { let num = +prompt(` 请选择您的操作: 1.取款 2.存款 3.查看余额 4.退出 `) if (num === 1) { let qu = +prompt('请您输入取款金额:') // money = money - qu money -= qu } else if (num === 2) { let cun = +prompt('请您输入存款金额:') // money = money + cun money += cun } else if (num === 3) { alert(`您的银行卡余额是: ${money}`) } else if (num === 4) { // 2.用户输入4则退出循环 break 一定要小心数据类型 break } } document.write(`滴,您的银行卡余额为: ${money}元,请节约消费`) ~~~ ## 循环嵌套 利用循环的知识来对比一个简单的天文知识,我们知道地球在自转的同时也在围绕太阳公转,如果把自转和公转都看成是循环的话,就相当于是循环中又嵌套了另一个循环。 实际上 JavaScript 中任何一种循环语句都支持循环的嵌套,如下代码所示: 基本语法: ~~~javascript for(初始化; 循环条件;变量计数) { for (初始化; 循环条件;变量计数){ // 要重复执行的代码 } } ~~~ 例如: ```html // 1. 外面的循环 记录第n天 for (let i = 1; i < 4; i++) { document.write(`第${i}天 <br>`) // 2. 里层的循环记录 几个单词 for (let j = 1; j < 6; j++) { document.write(`记住第${j}个单词<br>`) } } ``` 记住,外层循环循环一次,里层循环循环全部 ### 三角型 ~~~javascript // 外层打印几行 for (let i = 1; i <= 5; i++) { // 里层打印几个星星 for (let j = 1; j <= i; j++) { document.write('★') } document.write('<br>') } ~~~ ![image.png](https://cos.easydoc.net/84678576/files/lu9y5jsw.png) ### 九九乘法表 样式css ~~~css span { display: inline-block; width: 100px; padding: 5px 10px; border: 1px solid pink; margin: 2px; border-radius: 5px; box-shadow: 2px 2px 2px rgba(255, 192, 203, .4); background-color: rgba(255, 192, 203, .1); text-align: center; color: hotpink; } ~~~ javascript ~~~javascript // 外层打印几行 for (let i = 1; i <= 9; i++) { // 里层打印几个星星 for (let j = 1; j <= i; j++) { // 只需要把 ★ 换成 1 x 2 = 2 document.write(` <div> ${j} x ${i} = ${j * i} </div> `) } document.write('<br>') } ~~~ ![image.png](https://cos.easydoc.net/84678576/files/lu9y5dc0.png) ## 数组 > 知道什么是数组及其应用的场景,掌握数组声明及访问的语法。 ### 数组是什么? **数组**:(Array) 是一种数据类型,属于引用数据类型 **作用**: 在单个变量名下存储多个数据 例如我要保存咱们班同学的姓名,使用数组非常方便 ### 数组的基本使用 #### 定义数组 ```html <script> // 1. 语法,使用 [] 来定义一个空数组 // 定义一个空数组,然后赋值给变量 classes // let classes = [] // 2. 定义非空数组 let classes = ['小明', '小刚', '小红', '小丽', '小米'] </script> ``` 通过 `[]` 定义数组,数据中可以存放真正的数据,如小明、小刚、小红等这些都是数组中的数据,我们这些数据称为数组单元,数组单元之间使用英文逗号分隔。 #### 访问数组和数组索引 使用数组存放数据并不是最终目的,关键是能够随时的访问到数组中的数据(单元)。其实 JavaScript 为数组中的每一个数据单元都编了号,通过数据单元在数组中的编号便可以轻松访问到数组中的数据单元了。 我们将数据单元在数组中的编号称为索引值,也有人称其为下标。 索引值实际是按着数据单元在数组中的位置依次排列的,注意是从` 0` 开始的,如下图所示: ![image.png](https://cos.easydoc.net/84678576/files/lu9y54qh.png) 观察上图可以数据单元【小明】对应的索引值为【0】,数据单元【小红】对应的索引值为【2】 ```html <script> // 数组: 可以单个变量下存储多个数据 // 1. 声明数组 let names = ['小明', '小刚', '小红', '小丽', '小米'] // let names = ['小明', '小刚', true, '小丽', 1] console.log(names) // 1.1 数组是按照顺序来存储的,每个数据都有自己的编号 // 1.2 编号是从0开始的, 0 1 2 3... 也称为 索引 或者 下标 // 1.3 数组里面可以存放任意的数据类型 // 2. 数组取值 数组名[下标] console.log(names[0]) // '小明' console.log(names[1]) // '小刚' console.log(names[2]) // '小红' console.log(names[3]) // '小丽' console.log(names[4]) // '小米' </script> ``` 数组做为数据的集合,它的单元值可以是任意数据类型 ```html <script> // 6. 数组单值类型可以是任意数据类型 // a) 数组单元值的类型为字符类型 let list = ['HTML', 'CSS', 'JavaScript'] // b) 数组单元值的类型为数值类型 let scores = [78, 84, 70, 62, 75] // c) 混合多种类型 let mixin = [true, 1, false, 'hello'] </script> ``` #### 遍历数组 **遍历数组**:把数组中每个数据都访问到 **数组长度**: 数组.`length` ```html <script> let arr = ['迪丽热巴', '古力娜扎', '佟丽丫丫', '玛尔扎哈', '哈尼克孜'] // console.log(arr[0]) // console.log(arr[1]) // console.log(arr[2]) // console.log(arr[3]) // 遍历数组: 把数组里面的数据每个都会访问到 // for (let i = 0; i < 4; i++) { // // console.log(i) 数组名[索引号] // console.log(arr[i]) // } // 1. 数组的长度 数组.length // console.log(arr.length) // 4 for (let i = 0; i < arr.length; i++) { console.log(arr[i]) } // 2. 数组里面的数据也称为 数组元素 </script> ``` ### 操作数组 数组本质是数据集合, 操作数据无非就是 增 删 改 查 语法 ![image.png](https://cos.easydoc.net/84678576/files/lu9y4r15.png) #### 查询和修改数组 **查询:** ​ 语法:数组[索引] ​ 返回值:如果查询不到则返回 undefined **修改:** ​ 语法:数组[索引] = 新值 ​ 返回值:如果下标不存在,则是新增一个数组元素,并修改了数组长度(尽量避免) ```html <script> // 1. 查询数组元素 let arr = ['迪丽热巴', '古丽扎娜'] console.log(arr[0]) // '迪丽热巴' console.log(arr[1]) // '古丽扎娜' console.log(arr[2]) // undefined // 2. 修改数组元素 数组[索引] = 新值 arr[1] = '佟丽丫丫' // console.log(arr) arr[3] = '古丽扎娜' // 如果索引号不存在,则是增加数组元素 (不提倡) console.log(arr) console.log(arr.length) // 4 修改了数组长度 </script> ``` #### 新增 ![image.png](https://cos.easydoc.net/84678576/files/lu9y4hnz.png) ~~~javascript // 数组新增元素 // 1. 可以向数组的末尾新增1个或者多个数组元素 数组.push(元素1...元素n) let arr = ['迪丽热巴'] // console.log(arr.push('佟丽丫丫')) // 返回的是新数组的长度 2 // arr.push('佟丽丫丫', '古丽扎娜') // console.log(arr) // 修改原数组 // 2. 可以向数组的开头增加1个或者多个数组元素 数组.unshift(元素1,...元素n) // console.log(arr.unshift('佟丽丫丫')) // 返回的是新数组的长度 2 arr.unshift('佟丽丫丫', '古丽扎娜') console.log(arr) // 修改原数组 ~~~ #### 删除 ![image.png](https://cos.easydoc.net/84678576/files/lu9y4auj.png) ~~~javascript <script> // 删除元素 // 1. 删除数组中的最后一个元素 数组.pop() 修改原数组 let arr = ['red', 'green'] // arr.pop() // console.log(arr.pop()) // 返回的是被删除的元素 // console.log(arr) // 2. 删除数组中的第一个元素 数组.shift() 修改原数组的 arr.shift() // console.log(arr.shift()) // 返回的是被删除的元素 console.log(arr) </script> ~~~ #### 数组 splice方法 数组.splice() 方法 可以添加也可以删除数组元素 说明:可以从指定位置删除或者增加的数组元素,注意它修改原数组 > splice(start,deleteCount, item1, item2...) 1. start 起始位置: - 指定修改的开始位置(从0计数) 2. deleteCount 删除个数: - 表示要移除的数组元素的个数 - 可选的。如果省略则默认从指定的起始位置删除到最后 3. item1, item2... - 新增的元素 ~~~javascript <script> // splice 删除和增加数组元素 let arr = ['迪丽热巴', '古力娜扎', '佟丽丫丫', '玛尔扎哈'] // 1. splice 删除 数组.splice(起始位置, 删除几个) // arr.splice(1, 1) // 记住起始位置是索引号,从0 开始数 // arr.splice(1) // 如果第二个参数(删除几个)省略了,则默认删除到最后 // console.log(arr) // 2. splice 增加 数组.splice(起始位置, 删除几个, 新增元素1,...新增元素n) arr.splice(1, 0, '刘德华', 'pink老师') // 2.1 注意如果是新增,则起始位置是目标位置的索引号, 删除几个(第二个参数)不能省略我们写为 0, 后面写新增的元素 console.log(arr) // 3. splice 不是替换pop shift unshift push. arr.splice(0, 1) // 开头结尾找前面 pop shift unshift push // splice管中间 </script> ~~~ ## 综合案例 ### 手风琴效果 ![image.png](https://cos.easydoc.net/84678576/files/lu9y3zvs.png) 小技巧: 利用循环拼接字符串 (原理跟累加和类似) ①:声明一个空的字符串 str = '' ②:循环里面利用 += 进行拼接 ③:把拼接完毕的字符串放入容器中 完整代码: ~~~javascript <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .box { display: flex; overflow: hidden; width: 1120px; height: 260px; margin: 50px auto; } .box>div { width: 120px; border: 1px solid #fff; transition: all 0.5s; } .box>div:hover { width: 400px; } </style> </head> <body> <!-- <div class="box"> <div><img src="./images/1.jpg" alt=""></div> <div><img src="./images/2.jpg" alt=""></div> <div><img src="./images/3.jpg" alt=""></div> <div><img src="./images/4.jpg" alt=""></div> <div><img src="./images/5.jpg" alt=""></div> <div><img src="./images/6.jpg" alt=""></div> <div><img src="./images/7.jpg" alt=""></div> </div> --> <script> let arr = [ './images/1.jpg', './images/2.jpg', './images/3.jpg', './images/4.jpg', './images/5.jpg', './images/6.jpg', './images/7.jpg', ] // 1. 声明一个空的字符串变量 str let str = '' // 2. 利用for循环拼接字符串 += for (let i = 0; i < arr.length; i++) { // console.log(arr[i]) str += ` <div><img src="${arr[i]}" alt=""></div> ` } console.log(str) // 3. 把拼接的字符串放入 box盒子里面 document.write(` <div class="box"> ${str} </div> `) </script> </body> </html> ~~~ ### 根据数据渲染柱形图效果 ![image.png](https://cos.easydoc.net/84678576/files/lu9y27ea.png) 需求:用户输入四个季度的数据,可以生成柱形图 分析: ①:需要输入4次,所以可以把4个数据放到一个数组里面 - 声明一个空数组 - 利用循环,弹出4次框,同时把数据存到数组里面 ②:遍历该数组,根据数据生成4个柱形图,渲染打印到页面中 - 声明一个空字符串str - 根据数组利用循环拼接字符串,生成多个柱子 - 把生成的柱子添加到box盒子中 完整代码: ~~~javascript <!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>Document</title> <style> * { margin: 0; padding: 0; } body { background-color: #0c143d; } .box { display: flex; justify-content: space-around; align-items: flex-end; width: 800px; min-height: 300px; border-left: 1px solid #4b578f; border-bottom: 1px solid #4b578f; margin: 0 auto; padding-top: 50px; text-align: center; color: #9799ab; } .box>div { position: relative; display: flex; flex-direction: column; justify-content: space-between; width: 40px; height: 0; background: linear-gradient(#3c99ff, #4489d0, #2283e4); cursor: pointer; border-radius: 8px 8px 0 0; transition: all .2s; } .box>div:hover { animation: bg .5s alternate infinite; } @keyframes bg { to { box-shadow: 0 5px 29px rgb(53 111 226 / 88%); background: linear-gradient(#3c99ff, #68aff6, #2283e4); } } .box>div::after { content: ''; position: absolute; bottom: 0; left: 50%; width: 2px; height: 10px; background-color: #4b578f; transform: translate(-50%, 100%); } .box div span { width: 60px; margin: -30px 0 -5px -6px; } .box div h4 { width: 70px; margin: 0 0 -35px -10px; } .title { margin-top: 50px; text-align: center; color: #9799ab; } </style> </head> <body> <h3 class="title">2099年季度销售数额(单位万)</h3> <!-- <div class="box"> <div style="height: 123px;" title="第1季度-123万"> <span>123万</span> <h4>第1季度</h4> </div> <div style="height: 156px;" title="第2季度-156万"> <span>156万</span> <h4>第2季度</h4> </div> <div style="height: 120px;" title="第3季度-120万"> <span>120万</span> <h4>第3季度</h4> </div> <div style="height: 210px;" title="第4季度-210万"> <span>210万</span> <h4>第4季度</h4> </div> </div> --> <script> // 功能1: 用户输入4次,并且把数据存放到数组里面 // 1.1 声明一个空的数组 let arr = [] // 1.2 利用循环的形式让用户输入4次,并且把数据追加给数组 for (let i = 1; i <= 4; i++) { let num = +prompt(`请您输入第${i}季度的销售额`) arr.push(num) } console.log(arr) // 功能2:根据数组生成柱形图 // 2.1 声明一个空的字符串 str let str = '' // 2.2 利用循环拼接字符串,生成多个柱子 for (let i = 0; i < arr.length; i++) { str += ` <div style="height: ${arr[i]}px;" title="第${i + 1}季度-${arr[i]}万"> <span>${arr[i]}万</span> <h4>第${i + 1}季度</h4> </div> ` } console.log(str) // 2.3 把生成的柱子放到box盒子里面进行渲染 document.write(` <div class="box"> ${str} </div> `) </script> </body> </html> ~~~ ## 拓展知识 ### 数组排序sort 数组. sort() 方法可以排序 语法: ~~~javascript <script> // 数组排序 数组.sort() 修改原数组 let arr = [88, 78, 100, 34, 99] // arr.sort() // console.log(arr) // [100, 34, 78, 88, 99] // 1. 升序排序 // arr.sort(function (a, b) { // return a - b // }) // console.log(arr) // [34, 78, 88, 99, 100] // 2. 降序排序 arr.sort(function (a, b) { return b - a }) console.log(arr) // [100, 99, 88, 78, 34] // 3. 获取数组最大值和最小值 document.write(`数组的最大值:${arr[0]}`) document.write(`数组的最小值:${arr[arr.length - 1]}`) </script> ~~~ ### 选择排序(了解) 选择排序原理:(了解) 就是从第一个数开始,与后面所有的数相比较,找出最小(最大)的数,放在第一个位置 以此类推,每一轮确定一个相对于这一轮最小(最大)的数 算法可视化网站地址: https://visualgo.net/zh/sorting 核心:利用循环嵌套比较,根据索引号来交换变量 ①:外层循环是一共进行几轮相比较,通过观察,一共进行数组长度-1 次比较 - for (let i = 0; i < arr.length - 1; i++) - 把 i作为最小值起始索引 minIndex ②:里层循环是每一轮的比较来查找最小值 - 里层循环起始值是 i + 1 个元素开始查找 - for (let j = i + 1; j < arr.length; j++) - 进行比较的时候,发现最小的数组元素,把当前元素索引号给 minIndex ③:如果 minIndex 和 i 位置不一致,则交换变量 ~~~javascript <script> // 选择排序算法 let arr = [4, 2, 5, 1, 3] // 1 [1, 2, 5, 4, 3] // 2 [1, 2, 5, 4, 3] // 3 [1, 2, 3, 4, 5] // 4 [1, 2, 3, 4, 5] // 1. 外层循环控制是几轮能够比较出来 for (let i = 0; i < arr.length - 1; i++) { // 最小值的索引号 let minIndex = i // 2. 里层循环来查找最小值,并且记录最小值的索引号 for (let j = i + 1; j < arr.length; j++) { if (arr[j] < arr[minIndex]) { minIndex = j } } // 3. 交换变量 if (minIndex !== i) { let temp = arr[minIndex] arr[minIndex] = arr[i] arr[i] = temp } } console.log(arr) ~~~ # JavaScript 基础 - 第4天笔记 > 理解封装的意义,能够通过函数的声明实现逻辑的封装,知道对象数据类型的特征,结合数学对象实现简单计算功能。 - 函数 - 综合案例 ## 函数 > 理解函数的封装特性,掌握函数的语法规则 ### 函数的基本使用 **函数:** 是可以被重复使用的代码块 **作用:**函数可以把具有相同或相似逻辑的代码“包裹”起来,这么做的优势是有利于代码复用 #### 声明(定义)函数 声明(定义)一个完整函数包括关键字、函数名、形式参数、函数体、返回值5个部分 利用关键字 function 定义函数 (声明函数) 语法: ~~~javascript <script> // 函数: 是可以被重复使用的代码块,作用是有利于代码复用 // 1. 声明(定义)了最简单的函数,既没有形式参数,也没有返回值 function sayHi() { console.log('嗨~') } ~~~ 注意: 1. 函数名命名跟变量一致,采用`小驼峰`命名法 2. 函数名经常采用 动词 #### 调用 声明(定义)的函数必须调用才会真正被执行,使用 `()` 调用函数。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>JavaScript 基础 - 声明和调用</title> </head> <body> <script> // 声明(定义)了最简单的函数,既没有形式参数,也没有返回值 function sayHi() { console.log('嗨~') } // 函数调用,这些函数体内的代码逻辑会被执行 // 函数名() sayHi() // 可以重复被调用,多少次都可以 sayHi() </script> </body> </html> ``` > 注:函数名的命名规则与变量是一致的,并且尽量保证函数名的语义。 ### 函数的整体认知 **语法:** ~~~javascript function sum(参数1, 参数2...) {     return 结果 } console.log(sum(1, 2))  // 输出函数返回的结果 ~~~ **说明:** 1. 函数参数,如果有多个则用逗号分隔,用于接受传递过来的数据 2. return 关键字可以把结果返回给调用者 ### 函数参数 通过向函数传递参数,可以让函数更加灵活多变 ![image.png](https://cos.easydoc.net/84678576/files/lu9y91j7.png) **形参:**声明函数时小括号里的叫形参(形式上的参数) **实参:**调用函数时小括号里的叫实参(实际上的参数) **执行过程:** 会把实参的数据传递给形参,从而提供给函数内部使用,我们可以把形参理解为变量 我们曾经使用过的 alert('打印'),parseInt('11px'),Number('11')本质上都是函数调用的传参 ```html <script> // 函数的参数 形参和实参个数不匹配 // 1. 形参个数过多, 会自动补充 undefined function sum(x, y) { // 形参 return x + y } console.log(sum(1, 2)) // 实参 3 console.log(sum(1)) // 实参 NaN x = 1 y 没有给值默认值是 undefined // 1 + undefined = NaN // 2. 实参个数过多,则多余的实参会被忽略 console.log(sum(1, 2, 3)) // 实参 3 // 3. 开发中提倡要保证实参和形参个数统一 </script> ``` 在Javascript中 实参的个数和形参的个数可以不一致 - 如果形参过多 会自动填上undefined - 如果实参过多 那么多余的实参会被忽略 ### 逻辑中断 逻辑中断: 存在于逻辑运算符 && 和 || 中,左边如果满足一定条件会中断代码执行,也称为逻辑短路 >false && anything // 逻辑与左边false则中断,如果左边为true,则返回右边代码的值 > >true || anything // 逻辑或左边true则中断,如果左边为false,则返回右边代码的值 ~~~javascript <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 sum(x, y) { // return x + y // } // console.log(sum(1, 2)) // 3 // console.log(sum()) // NaN function sum(x, y) { // x = undefined // x = undefined || 0 // x = 1 || 0 x = x || 0 y = y || 0 return x + y } console.log(sum()) // 0 console.log(sum(1, 2)) // 3 </script> ~~~ ### 函数默认参数 默认参数:可以给形参设置默认值 > 说明:这个默认值只会在缺少实参传递或者实参是undefined才会被执行 **默认参数和逻辑中断使用场景区别:** 1. 默认参数主要处理函数形参(处理参数要比逻辑中断更简单) 2. 逻辑中断除了参数还可以处理更多的需求 ~~~javascript <script> // 默认参数: 给形参一个默认值 // 1. 默认参数里面的值执行: // 1.1 没有实参传递过来 x = 0 // 1.2 有实参传递但是传递的是undefined x = 0 function sum(x = 0, y = 0) { return x + y } console.log(sum()) // 0 console.log(sum(undefined, undefined)) // 0 console.log(sum(1, 2)) // 3 // 2. 默认参数和逻辑中断使用场景的区别: // 2.1 默认参数主要针对的是形参 // 2.2 逻辑中断除了处理参数之外,还可以做更多 </script> ~~~ ### 函数返回值 函数的本质是封装(包裹),函数体内的逻辑执行完毕后,函数外部如何获得函数内部的执行结果呢? 要想获得函数内部逻辑的执行结果,需要通过 `return` 这个关键字,将内部执行结果传递到函数外部,这个被传递到外部的结果就是返回值。 > 返回值:把处理结果返回给调用者 ```html <script> // 函数返回值细节 // 1. return 结束函数,return 后面的代码不会执行了, break退出循环或者switch // function sum(x, y) { // return x + y // console.log('我不会执行') // } // console.log(sum(1, 3)) // 2. return 和被返回的结果不要换行 // function sum(x, y) { // return // x + y // } // console.log(sum(1, 3)) // 3. 如果函数没有return 则默认返回的是 undefined function fn() { } console.log(fn()) // undefined </script> ``` 总结: 1. return会立即结束当前函数,所以后面代码不会再被执行 2. 在 return 关键字和被返回的表达式之间不允许使用换行符,否则内部执行相当于会自动补充分号 3. 函数可以没有 return,这种情况函数默认返回值为 undefined ### 作用域 **作用域(scope)**: 变量或者值在代码中可用性的范围 **作用:**作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。 #### 全局作用域 作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件 处于全局作用域内的变量,称为全局变量 #### 局部作用域 1. 函数作用域。作用于函数内的代码环境 2. 块级作用域。{ } 大括号内部 处于局部作用域内的变量称为局部变量 >注意: > >1. 如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐 >2. 但是有一种情况,函数内部的形参可以看做是局部变量。 #### 变量的访问原则 访问原则:在能够访问到的情况下先局部,局部没有再找全局,总结: `就近原则` ### 匿名函数 函数可以分为具名函数和匿名函数 匿名函数:没有名字的函数,无法直接使用。 #### 函数表达式 将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式 ~~~javascript // 声明 let fn = function() { console.log('函数表达式') } // 调用 fn() ~~~ 总结: 1. 其实函数也是一种数据类型 2. 函数表达式必须先定义,后使用 3. 函数的形参和实参使用跟具名函数一致 #### 立即执行函数 IIFE (立即执行函数表达式) (Immediately Invoked Function Expression) **场景介绍:** 避免全局变量之间的污染 **注意:**多个立即执行函数要用 ; 隔开,要不然会报错 ~~~javascript (function(){ xxx })(); (function(){xxxx}()); ~~~ ## 综合案例 ![image.png](https://cos.easydoc.net/84678576/files/lu9y8m79.png) 需求:用户输入秒数,可以自动转换为时分秒 分析: ①:用户弹窗输入 总秒数 ②:封装函数 getTime, 计算时分秒,注意:里面包含数字补0 ③:打印输出 计算公式:计算时分秒 小时: h = parseInt(总秒数 / 60 / 60 %24) 分钟: m = parseInt(总秒数 / 60 % 60 ) 秒数: s = parseInt(总秒数 % 60) 完整代码: ~~~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> ~~~