一、为什么需要函数
函数:function,是被设计为执行特定任务的代码块。代码复用
二、函数使用
1. 函数的声明语法
function 函数名() {函数体}
2. 函数名命名规范
-
和变量名基本一致
-
尽量小驼峰命名法
-
前缀应该为动词
-
命名建议:常用动词约定
动词 | 含义 |
---|---|
can | 判断是否可执行某个动作 |
has | 判断是否含义某个值 |
is | 判断是否为某个值 |
get | 获取某个值 |
set | 设置某个值 |
load | 加载某些数据 |
function getName() {}
function addSquares() {}
3. 函数调用
//函数调用,这些函数体内的代码逻辑会被执行
函数名()
//函数一次声明可以多次调用,每一次函数调用函数体里面的代码会重新执行一次
alert() , parseInt() 这种名字后面跟小括号的本质都是函数的调用
三、函数传参
1. 有参数的函数声明和调用
声明语法
function 函数名(参数列表) {函数体}
参数列表:
- 传入数据列表
- 声明这个函数需要传入几个数据
- 多个数据用逗号隔开
调用语法
函数名(传递的参数列表)
-
形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
-
实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
-
形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值
-
开发中尽量保持形参和实参个数一致
-
alert(‘打印’), parseInt(‘11’), Number(‘11’) 本质上都是函数调用的传参
2. 逻辑中断
形参如果不被赋值,就是undefined
function getSum(x, y) {x = x || 0y = y || 0document.write(x + y)}// 调用getSum(1, 2)
3. 求学生总分
// 求学生总分// 声明函数function getScore(arr) {let sum = 0for (let i = 0; i < arr.length;i++) {sum += arr[i]}document.write(sum)}// 调用getScore([90, 10, 100, 50])
四、函数返回值
return 数据function getSum(x, y) {x = x || 0y = y || 0// 先计算x + y 再返回return x + y}let sum = getSum(1, 2)document.write(sum)
用return返回数据
- 在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
- 函数内部只能出现 1 次 return,并且 return 后面代码不会再被执行,所以 return 后面的数据不要换行写
- return会立即结束当前函数
- 函数可以没有 return,这种情况函数默认返回值为 undefined
求一个数组的最大值和最小值
// 求一个数组最大值和最小值function getMaxAndMin(arr) {// 1. 声明变量let max = arr[0]let min = arr[0]// 2. 遍历循环for (let i = 1; i < arr.length; i++) {if (max < arr[i]) {max = arr[i]}if (min > arr[i]) {min = arr[i]}}// 3. 返回值return [max, min]}let value = getMaxAndMin([1, 5, 2, 8, 0])document.write(`数组最大值:${value[0]},数组最小值:${value[1]}`)
求两个数的最大值
// 求两个数的最大值let num1 = +prompt('请输入第一个数')let num2 = +prompt('请输入第二个数')// 比较函数,最大值function getMax(x, y) {// if (x > y) {// return x// } else {// return y// }return x > y ? x : y}let max = getMax(num1, num2)document.write(max)
五、作用域
1. 作用域概述
全局作用域:全局有效,作用于所有代码执行的环境(整个script标签内部)或者一个独立的js文件
局部作用域:局部有效,作用于函数内的代码环境,就是局部作用域。因为跟函数有关系,所以也称为函数作用域。
块级作用域:{}内有效,块作用域由{}包括,if语句和for语句里面的{}等
2. 变量的作用域
全局变量:函数外部let的变量,全局变量在任何区域都可以访问和修改
局部变量:函数内部let的变量,局部变量只能在当前函数内部访问和修改
块级变量:{}内部的let变量,let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问
3. 特殊情况
如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐。函数内部的形参可以看做是局部变量。
4. 变量访问原则-作用域链
-
只要是代码,就至少有一个作用域
-
写在函数内部的局部作用域
-
如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
-
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作作用域链
作用域链:采取就近原则的方式来查找变量最终的值
六、匿名函数
将匿名函数赋值给一个变量,并且通过变量名称进行调用 我们将这个称为函数表达式
// 声明
let fn = function () {// 函数体
}
// 调用
fn() // 函数名
<body><button>点击我</button><script>let btn = document.querySelector("button")btn.addEventListener(function() {alert('匿名函数')})</script>
</body>
<body><button>点击我</button><script>let btn = document.querySelector("button")btn.onclick = function() {alert('弹出')}</script>
</body>
立即执行函数
避免全局变量之间的污染
(function() { console.log(111) })();
(function() { console.log(111) }();
// 不需要调用,立即执行
多个立即执行函数要用;
隔开
七、综合案例
用户输入秒数,可以自动转换为时分秒
// 1. 用户输入秒数let seconds = +prompt('请输入总的秒数:')// 2. 计算时分秒(封装函数)里面包含数字补0function getTimes(t) {// 小时: h = parseInt(总秒数 / 60 / 60 % 24)// 分钟: m = parseInt(总秒数 / 60 % 60 )// 秒数: s = parseInt(总秒数 % 60)let h = parseInt(t / 60 / 60 % 24)let m = parseInt(t / 60 % 60 )let s = parseInt(t % 60)h = h < 10 ? '0' + h : hm = m < 10 ? '0' + m : ms = s < 10 ? '0' + s : sreturn `计算之后的时间是${h}小时${m}分${s}秒`}// 3. 打印输出let str = getTimes(seconds)document.write(str)
Caroline Finish 2022/12/6