//函数:封装代码 提高复用性<br /> //函数不调用 自己不执行<br /> //命名建议 应该为动词
//语法:<br /> function函数名() {<br /> }<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/25421229/1639012257950-bdd53055-a7a2-4c49-a958-1da73bda8d42.png#clientId=ue1a608b0-9530-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=291&id=u5ca2dd12&margin=%5Bobject%20Object%5D&name=image.png&originHeight=240&originWidth=454&originalType=binary&ratio=1&rotation=0&showTitle=false&size=34781&status=done&style=none&taskId=ua1676385-1c84-4b24-8aab-2958b3649fc&title=&width=550.9886322021484)
函数:
function,是被设计为执行特定任务的代码块
1.为什么需要函数?
可以实现代码复用,提高开发效率
2.为什么要有参数的函数?
若函数完成功能需要调用者传入数据,那么就需要用有参数的函数,这样可以极大提高函数的灵活性
3.为什么要让函数有返回值
函数执行后得到结果,结果是调用者想要拿到的(一句话,函数内部不需要输出结果,而是返回结果)
对执行结果的扩展性更高,可以让其他的程序使用这个结果
小结:
函数是用那个关键字声明的?
function
函数不调用会执行吗?如何调用函数?
函数不调用自己不执行
调用方式: 函数名()
函数的复用代码和循环重复代码有什么不同? 循环代码写完即执行,不能很方便控制执行位置
随时调用,随时执行,可重复调用
封装冒泡排序:
<script>
function getMaopao(arr) {
let temp = 0;
for (let j = 0; j < arr.length - 1; j++) {
for (let i = 0; i < arr.length - j - 1; i++) {
if (arr[i] > arr[i + 1]) {
temp = arr[i + 1];
arr[i + 1] = arr[i]
arr[i] = temp;
}
}
}
return arr;
}
let arr = [12, 31, 423, 42, 32, 22]
let maopao = getMaopao(arr);
console.log(maopao);
</script>
封装数组最大最小值:
//求一个数组最大值和最小值
function getMaxAndMin(arr) {
//1.声明一个最大值变量和最小值变量
let max = arr[0];
let min = arr[0];
for (let i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i]
}
if (min > arr[i]) {
min = arr[i]
}
}
//return只能返回一个值,可以是任何类型 如果需要返回多个值 可以用数组存储
return [max, min]
}
let arr = [1, 2, 42, 12, 412, 32]
let value = getMaxAndMin(arr);
console.log(value);
4.函数命名规范:
5.有参数的函数声明和调用
注意:声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数
是有利于精简代码方便复用。
函数的使用: 声明函数 和 调用函数
function 是声明函数的关键字 必须小写
6.形参和实参
//形参:其实就是一个变量而已 这个变量只在函数内部使用 形式参数
//实参:具体的数据
形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
形参可以理解为是在这个函数内部声明的变量(比如 num1 = 10)
实参可以理解为是给这个变量赋值
开发中尽量保持形参和实参个数一致
参数中间用(,)逗号隔开
当函数需要返回数据出去时,用return关键字
细节:
1.在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
2.函数内部只能出现 1 次 return,并且 return 后面代码不会再被执行,所以 return 后面的数据不要换行写 3.return会立即结束当前函数
函数可以没有 return,这种情况函数默认返回值为 undefined
作用域
- 作用域概述:
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这
个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。 - 变量的作用域:
在JavaScript中,根据作用域的不同,变量可以分为
变量有一个坑, 特殊情况:
如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
但是有一种情况,函数内部的形参可以看做是局部变量。
- 变量访问原则-作用域链
1.只要是代码,就至少有一个作用域
2.写在函数内部的局部作用域
3.如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
4.根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链 - 变量访问原则是什么?
作用域链:采取就近原则的方式来查找变量最终的值
匿名函数
匿名函数
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式//匿名函数
//函数表达式
//将一个函数 作为一个值 赋值给一个变量
let a = function () {
console.log(1)
}
a();//函数调用
let fn = function (num1) {
console.log(num1)
}
fn(10);//调用函数 传参
- 立即执行函数(了解即可)
立即执行函数有什么作用?
防止变量污染
立即执行函数需要调用吗? 有什么注意事项呢?
无需调用,立即执行,其实本质已经调用了
多个立即执行函数之间用分号隔开
每日一练:
1.封装求和:
2.计算m - n之间所有数的和
<script>
//计算m - n之间所有数的和
//1.封装函数 形参 m,n
function getSum(m, n) {
//2.定义求和变量
let sum = 0;
// 5.增加判断 因为遍历是从m~n 如果m>n就遍历不了 得不到结果 所以当m>n时就交换他们的数字
let temp;
if (m > n) {
temp = m;
m = n;
n = temp;
}
//3.遍历 得到m~n中间的每一个数
for (let i = m; i <= n; i++) {
// 4.求m~n之间所有数的和
sum = sum + i;
}
return sum;
}
// 6.提示用户输入用变量接收
let a = +prompt('请输入第一个数字')
let b = +prompt('请输入第二个数字')
// 7.调用函数 将用户输入的数字 以实参的方式 传递至形参 并与变量接收保存
let res = getSum(a, b)
// 8.打印输出
document.write(`${a}到${b}之间的和是${res}`);
</script>
3.计算时间综合案例
<script>
/* 小时: h = parseInt(总秒数 / 60 / 60 % 24)
分钟: m = parseInt(总秒数 / 60 % 60)
秒数: s = parseInt(总秒数 % 60) */
// 1.用户输入时间 弹出输入框
let time = +prompt('请输入毫秒数')
//2.函数封装 计算时间功能
function getTime(t) {
//计算时间公式
let h = parseInt(t / 60 / 60 % 24)
let m = parseInt(t / 60 % 60)
let s = parseInt(t % 60)
//4.调用补零函数
h = buLing(h)
m = buLing(m)
s = buLing(s)
//5.返回 用字符串模板渲染之后的 小时 分钟 秒
return `${h}时 ${m}分 ${s}秒`
}
//3.对补零功能 进行函数封装
function buLing(n) {
//三元表达式补零 操作 返回结果
return n < 10 ? '0' + n : n
}
//6.调用函数 用变量接收函数数据 将用户输入的数据(实参) 传输给 (形参) 返回调用
let jieshou = getTime(time)
document.write(`计算之后的时间是:${jieshou}`)
</script>
4.学生的分数是一个数组, 计算每个学生的总分
// 题目. 学生的分数是一个数组, 计算每个学生的总分
// 9.封装函数 求数组和
function getScore() {
// 10.调用课程分数数组 赋值给arr
let arr = zongkecheng();
//11.定义求和变量
let sum = 0;
//12.遍历调用过来的课程数组
for (let i = 0; i < arr.length; i++) {
// 13.依次将结果赋值给sum 得到总分数;
sum = sum + arr[i]
}
// 14.返回总分数
return sum;
}
// 15.调用数组求和函数 用变量接收
let chengji = getScore()
//16.打印成绩
document.write(`<br>您的总分数为:${chengji}分`)
//1.定义函数 封装学生每一门的课程分数 用数组保存并反回
function zongkecheng() {
//2.提示框
let n = prompt('你有几门课程')
//3.判断条件
if (n <= 0) {
alert('请重新输入')
} else {
//4.定义空数组 用来存储分数
let arr = []
//这句话不需要重复打印
document.write(`你的分数分别是:`)
// 5.遍历 从 1到 n门课程结束
for (let i = 1; i <= n; i++) {
//6.依次将分数添加到空数组
arr.push(+prompt('第' + i + '门课程的分数是:'))
//7.打印
document.write(`<br>第${i}门课程的分数是:${arr[i - 1]}分`)
}
//8.返回记录了分数的数组
return arr;
}
}