函数
初识函数
函数的基本认识
1.什么是函数
function,是被设计为执行特定任务的代码块。
2.为什么需要函数
可以实现代码复用,提高开发效率。函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。
函数使用
1.函数语法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q0p9pmUc-1648729284321)(06-函数.assets/1648692531197.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XxgP15IH-1648729284321)(06-函数.assets/1648692548770.png)]
2.函数命名规范
- 和变量命名基本一致
- 尽量小驼峰式命名法
- 前缀应该为动词
- 命名建议:常用动词约定
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WWLfwHxr-1648729284322)(06-函数.assets/1648692621489.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Z04TeP4v-1648729284322)(06-函数.assets/1648692697877.png)]
3.函数调用
-
函数调用语法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GWKJ9YHI-1648729284323)(06-函数.assets/1648693422612.png)]
注意:声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数
-
调用的举例
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-w6RYowY3-1648729284323)(06-函数.assets/1648693466167.png)]
我们曾经使用的 alert() , parseInt() 这种名字后面跟小括号的本质都是函数的调用
-
函数体
函数体是函数的构成部分,它负责将相同或相似代码“包裹”起来,直到函数调用时函数体内的代码才会被执行。函数的功能代码都要写在函数体当中。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2f1S2iVt-1648729284323)(06-函数.assets/1648693849502.png)]
4.代码展示
<script>
// 1.声明函数
/* 语法:
function 函数名(){}
*/
function skyGoods() {
console.log('伙计, 加油!');
console.log('伙计, 你很棒!');
}
// 2.调用函数 函数名()
skyGoods()
skyGoods()
</script>
5.练习:使用函数打印3次99乘法表
<script>
// 1.声明函数 打印99乘法表
function getSum() {
for (let index = 1; index <= 9; index++) {
for (let index1 = 1; index1 <= index; index1++) {
let num = index1 * index;
document.write(`<span> ${index1} * ${index} = ${num} </span>`);
}
document.write('<br/>');
}
}
// 2,调用函数
getSum();
getSum();
getSum();
</script>
6.练习封装函数
-
封装一个函数,计算两个数的和
代码展示:
<script> function getSum() { let num1 = 3; let num2 = 6; console.log(num1 + num2); } getSum(); </script>
-
封装一个函数,计算1-100之间所有数的和
代码展示:
<script> let sum = 0 function getSum() { for (let index = 1; index <= 100; index++) { sum += index } console.log(sum); } getSum() </script>
7.总结
- 函数使用关键字 function 声明
- 函数需要进行调用才会执行,调用方式: 函数名()
- 函数相比循环代码的优势:
- 循环代码写完即执行,不能很方便控制执行位置
- 随时调用,随时执行,可重复调用
函数传参
我们刚才学习的封装函数的案例中,只能输出固定的数据,不能灵活指定数字输出,有很大的局限性。把要计算的数字传到函数内,那要如何解决这个问题呢?让我们了解一下函数的传参
传参的定义跟使用
定义
- 为什么需要传参
- 若函数完成功能需要调用者传入数据,那么就需要用有参数的函数
- 这样可以极大提高函数的灵活性
- 传参的作用
- 让用户输入自己想要的数据进行处理
使用
1.参数的函数声明
-
声明语法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MD0QjVZ8-1648729284323)(06-函数.assets/1648696220385.png)]
-
参数列表:
- 传入数据列表
- 声明这个函数需要传入几个数据
- 多个数据用逗号隔开
-
单个参数跟多个参数展示
-
单个参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2tTUlvJi-1648729284324)(06-函数.assets/1648696297335.png)]
-
多个参数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wzVUJWaQ-1648729284324)(06-函数.assets/1648696309304.png)]
-
2.有参数的函数声明和调用
-
调用语法:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p0ZRnZKQ-1648729284324)(06-函数.assets/1648696352234.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jsQx1tRS-1648729284324)(06-函数.assets/1648696383938.png)]
-
调用函数时,需要传入几个数据就写几个,用逗号隔开
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B6nonYQL-1648729284324)(06-函数.assets/1648696428494.png)]
-
代码展示
<script> // 函数的形参跟实参 // 定义函数 function getSum(num1, num2) { console.log(num1 + num2); } //调用函数 getSum(12, 20) </script>
函数传参
传参分为形参跟实参
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NxU8mnBc-1648729284325)(06-函数.assets/1648696578859.png)]
- 形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
- 实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
- 形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
- 开发中尽量保持形参和实参个数一致
- 我们曾经使用过的 alert(‘打印’), parseInt(‘11’), Number(‘11’) 本质上都是函数调用的传参
如果输入的实参个数大于形参的个数,多余的实参不会运行(你输入的实参再多,如果形参只有3个,它也只会运行3个——按照形参的个数而定)。
代码展示:
<script>
// 函数的形参跟实参
// 定义函数
function getSum(num1, num2) {
console.log(num1 + num2);
}
//调用函数
getSum(12, 20, 40)
</script>
案例
1.计算学生[66, 77, 88, 99, 89]的总分
<script>
let num = [66, 77, 88, 99, 89], sum = 0
function calcSum() {
for (let index = 0; index < num.length; index++) {
sum += num[index]
}
console.log(sum);
}
calcSum()
</script>
2.计算多个学生的总分
<script>
// 定义函数
function calcSum(arr) {
let sum = 0
// 遍历循环数组
for (let index = 0; index < arr.length; index++) {
sum += arr[index]
}
console.log(sum);
}
// 数组
let num1 = [66, 77, 88, 99, 89]
let num2 = [12, 34, 56, 76, 87, 45]
let num3 = [1, 2, 3, 4, 5, 6, 7, 8]
// 调用函数
calcSum(num1)
calcSum(num2)
calcSum(num3)
</script>
3.计算数组的和
<script>
function getMax(array) {
// let num = [1, 3, 45, 6, 7, 89, 22]
let max = array[0]
// 遍历循环数组
for (let index = 0; index < array.length; index++) {
if (max < array[index]) {
max = array[index]
}
}
console.log(max);
}
// 调用函数
// getMax(num)
getMax([333, 43, 54, 56, 999])
</script>
4.计算数组奇数和
分析:遇到这种情况,最好是先写出求奇数和的代码,然后在将改代码嵌入到函数中
<script>
// 步骤:先单独写出求奇数的和,在嵌套入函数中
// let num = [1, 3, 5, 6, 7, 78, 9, 45, 63]
// let sum = 0
// // 计算出奇数的和
// for (let index = 0; index < num.length; index++) {
// if (num[index] % 2 !== 0) {
// sum += num[index]
// }
// }
// console.log(sum);
// 定义函数
function getSum(arr) {
// let num = [1, 3, 5, 6, 7, 78, 9, 45, 63]
let sum = 0
// 计算出奇数的和
// 循环数组
for (let index = 0; index < arr.length; index++) {
// 检查元素是否为奇数
if (arr[index] % 2 !== 0) {
sum += arr[index]
}
}
console.log(sum);
}
// 调用函数
getSum([1, 2, 3])
</script>
函数返回值
1.什么是函数返回值?
- 当调用某个函数,这个函数会返回一个结果出来
- 这就是有返回值的函数
2.用return返回数据
当函数需要返回数据出去时,用return关键字
1.语法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P8Uuqb4C-1648729284325)(06-函数.assets/1648712641870.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pQePB6rZ-1648729284325)(06-函数.assets/1648712653138.png)]
2.使用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rLWm3wlQ-1648729284325)(06-函数.assets/1648712715330.png)]
3.函数返回值的使用场景
代码展示:求两个数之间的最大值
<script>
function getMax(n1, n2) {
if (n1 > n2) {
return n1
} else {
return n2
}
}
document.write(getMax(100, 99))
alert(getMax(19.9, 10))
</script>
4.训练
求数组中的最大值及最小值
<script>
// let arr1 = [123, 4, 5, 677, 78, 45]
function getMax(arr1) {
// 求最大值
let max = arr1[0]
for (let index = 0; index < arr1.length; index++) {
if (max < arr1[index]) {
max = arr1[index]
}
}
return max
}
alert(getMax([123, 4, 5, 677, 78, 45]))
function getMin(arr2) {
// 求最小值
let min = arr2[0]
for (let index = 0; index < arr2.length; index++) {
if (min > arr2[index]) {
min = arr2[index]
}
}
return min
}
console.log(getMin([123, 4, 5, 677, 78, 45]));
</script>
3.注意事项
- 在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
- 函数内部只能运行到 1 次 return,并且 return 后面代码不会再被执行
- 所以 return 后面的数据不要换行写
- return会立即结束当前函数
- 函数可以没有 return,这种情况函数默认返回值为 undefined
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W9Vlh2Uu-1648729284326)(06-函数.assets/1648713555507.png)]
作用域
1.作用域介绍
作用域概念
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
作用域分类
- 全局作用域
- 特性:全局有效
- 作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
- 局部作用域
- 特性:局部有效
- 作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域
- 块级作用域
- {} 内有效
- 块作用域由 { } 包括,if语句和for语句里面的{ }等
变量的作用域
在JavaScript中,根据作用域的不同,变量可以分为
- 全局变量
- 函数外部let 的变量
- 全局变量在变量定义之后区域可以访问和修改
- 局部变量
- 函数内部let的变量
- 局部变量只能在当前函数内部访问和修改
- 块级变量
- {} 内部的let变量
- let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
- 细节:
- 局部变量或者块级变量 没有let 声明直接赋值的当全局变量看,我们强烈不提倡
- 还有一种特殊情况,函数内部的形参可以当做局部变量看
2.作用域链
在不同作用域下,可能存在变量命名冲突的情况,到底改执行谁呢?
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bGxvXAa3-1648729284326)(06-函数.assets/1648719159981.png)]
这个时候就需要作用域链来确定变量的值。
作用域链:采取就近原则的方式来查找变量最终的值
变量访问元组—作用域链
- 只要是代码,就至少有一个作用域
- 写在函数内部的局部作用域
- 如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
- 根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
解析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BWnMaBMF-1648729284326)(06-函数.assets/1648718498435.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cOoNqNjk-1648729284326)(06-函数.assets/1648721726957.png)]
匿名函数
函数按照有没有名字,分成两种
- 有名字 具名函数:声明:function fn() {}
调用:fn() - 没有名字 匿名函数:function() {}
定义及语法
1.匿名函数
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
2.语法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nB2i9ntD-1648729284326)(06-函数.assets/1648721964803.png)]
调用:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZyRcbX8r-1648729284327)(06-函数.assets/1648721990898.png)]
其中函数的形参和实参使用跟具名函数一致。
3.使用场景
后期 web API 会使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QdjFhFC0-1648729284327)(06-函数.assets/1648722056871.png)]
立即执行函数
(书写之后立即执行,无需调用)
场景介绍: 避免全局变量之间的污染
语法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VCHSQJeR-1648729284327)(06-函数.assets/1648722115581.png)]
注意: 多个立即执行函数要用 ; 隔开,要不然会报错
k-1648729284326)]
匿名函数
函数按照有没有名字,分成两种
- 有名字 具名函数:声明:function fn() {}
调用:fn() - 没有名字 匿名函数:function() {}
定义及语法
1.匿名函数
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
2.语法
[外链图片转存中…(img-nB2i9ntD-1648729284326)]
调用:
[外链图片转存中…(img-ZyRcbX8r-1648729284327)]
其中函数的形参和实参使用跟具名函数一致。
3.使用场景
后期 web API 会使用
[外链图片转存中…(img-QdjFhFC0-1648729284327)]
立即执行函数
(书写之后立即执行,无需调用)
场景介绍: 避免全局变量之间的污染
语法
[外链图片转存中…(img-VCHSQJeR-1648729284327)]
注意: 多个立即执行函数要用 ; 隔开,要不然会报错