> 文章列表 > 【函数】JavaScript 全栈体系(七)

【函数】JavaScript 全栈体系(七)

【函数】JavaScript 全栈体系(七)

JavaScript 基础

第十三章 函数

一、为什么需要函数

函数:

  • function,是被设计为执行特定任务的代码块

说明:

  • 函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于 精简代码方便复用。
  • 比如我们前面使用的 alert() 、 prompt() 和 console.log() 都是一些 js 函数,只不过已经封装好了,我们直接使用的 。

二、函数使用

函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。

1. 声明(定义)

声明(定义)一个完整函数包括关键字、函数名、形式参数、函数体、返回值5个部分
在这里插入图片描述

2. 函数名命名规范

  • 变量命名基本一致
  • 尽量小驼峰式命名法
  • 前缀应该为动词
  • 命名建议:常用动词约定

3. 调用

声明(定义)的函数必须调用才会真正被执行,使用 () 调用函数。

<!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>
</head><body><script>// let num = 10// console.log(num)// 1. 函数的声明   function sayHi() {console.log('hi~~~')}// 2. 函数调用   函数不调用,自己不执行sayHi()sayHi()sayHi()</script>
</body></html>

注:函数名的命名规则与变量是一致的,并且尽量保证函数名的语义。

4. 案例

需求:

  1. 封装一个函数,计算两个数的和
  2. 封装一个函数,计算1-100之间所有数的和
<!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>
</head><body><script>// 1. 求2个数的和// function getSum() {//   let num1 = +prompt('请输入第一个数')//   let num2 = +prompt('请输入第二个数')//   console.log(num1 + num2)// }// getSum()// 2. 求 1~100 累加和function getSum() {let sum = 0for (let i = 1; i <= 100; i++) {sum += i}console.log(sum) // 5050}getSum()</script>
</body></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>Document</title>
</head><body><script>// 2. 求 1~100 累加和// function getSum(end) {   // end = 50//   // console.log(end)//   let sum = 0//   for (let i = 1; i <= end; i++) {//     sum += i//   }//   console.log(sum)// }// getSum(50)  // 1~50// getSum(100)  // 1~100function getSum(start, end) {   // end = 50// 形参  形式上的参数  // console.log(end)let sum = 0for (let i = start; i <= end; i++) {sum += i}console.log(sum)}getSum(1, 50)  // 调用的小括号里面 实参 - 实际的参数 1275getSum(100, 200)  // 实参 - 实际的参数 15150</script>
</body></html>

总结:

  1. 声明(定义)函数时的形参没有数量限制,当有多个形参时使用 , 分隔
  2. 调用函数传递的实参要与形参的顺序一致

1. 形参和实参

形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)

实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)

形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)实参可以理解为是给这个变量赋值

开发中尽量保持形参和实参个数一致

<!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>
</head><body><script>// 函数求和// function getSum(x = 0, y = 0) {//   // x = 1//   // num1 默认的值 undefined//   document.write(x + y)// }// getSum(1, 2)// getSum()  // 0function getSum(start = 0, end = 0) {   // end = 50// 形参  形式上的参数// console.log(end)let sum = 0for (let i = start; i <= end; i++) {sum += i}console.log(sum)}getSum(1, 50)  // 调用的小括号里面 实参 - 实际的参数 1275getSum(100, 200)  // 实参 - 实际的参数 15150getSum() // 0</script>
</body></html>

2. 案例:函数封装求和

  • 需求:采取函数封装的形式:输入2个数,计算两者的和,打印到页面中
<!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>
</head><body><script>// 1. 封装函数// 给一个参数的默认值function getArrSum(arr = []) {// console.log(arr)let sum = 0for (let i = 0; i < arr.length; i++) {sum += arr[i]}console.log(sum)}getArrSum([1, 2, 3, 4, 5]) // 15getArrSum([11, 22, 33]) // 66getArrSum()  // 0</script>
</body></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>Document</title>
</head><body><script>// 求 n ~ m 的累加和function getSum(n = 0, m = 0) {let sum = 0for (let i = n; i <= m; i++) {sum += i}console.log(sum)}// getSum()// getSum(1, 2)let num1 = +prompt('请输入起始值:')let num2 = +prompt('请输入结束值:')// 调用函数getSum(num1, num2)  // 实参可以是变量</script>
</body></html>

四、返回值

函数的本质是封装(包裹),函数体内的逻辑执行完毕后,函数外部如何获得函数内部的执行结果呢?要想获得函数内部逻辑的执行结果,需要通过 return 这个关键字,将内部执行结果传递到函数外部,这个被传递到外部的结果就是返回值。

<!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>
</head><body><script>// // 函数的返回值// function fn() {//   return 20// }// // fn() 调用者 相当于执行了    fn()   = 20// // return 的值返回给调用者// // console.log(fn())// // let num = prompt('请输入数字')// let re = fn()// console.log(re)// 求和函数的写法function getTotalPrice(x, y) {return x + y// return 后面的代码不会被执行}// console.log(getTotalPrice(1, 2))// console.log(getTotalPrice(1, 2))let sum = getTotalPrice(1, 2)console.log(sum) // 3console.log(sum) // 3function fn() {}let re = fn()console.log(re)  // undefined</script>
</body></html>

总结:

  1. 在函数体中使用return 关键字能将内部的执行结果交给函数外部使用
  2. 函数内部只能出现1 次 return,并且 return 下一行代码不会再被执行,所以return 后面的数据不要换行写
  3. return会立即结束当前函数
  4. 函数可以没有return,这种情况默认返回值为 undefined
<!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></head><body><div></div><script>// 1. 求最大值函数// function getMax(x, y) {//   return x > y ? x : y// }// let max = getMax(11, 234)// console.log(max)// //  2. 求任意数组的最大值,并且返回// function getArrValue(arr = []) {//   // (1)先准备一个max变量存放数组的第一个值//   let max = arr[0]//   // (2) 遍历比较//   for (let i = 1; i < arr.length; i++) {//     if (max < arr[i]) {//       max = arr[i]//     }//   }//   // (3) 返回值//   return max// }// // let max = getArrValue([1, 3, 5, 7, 9])// // let num = prompt('请输入')// let max = getArrValue([11, 3, 55, 7, 29])// console.log(max)//  3. 求任意数组的最大值和最小值,并且返回function getArrValue(arr = []) {// (1)先准备一个max变量存放数组的第一个值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]// return min}let newArr = getArrValue([11, 3, 55, 7, 29])console.log(`数组的最大值是: ${newArr[0]}`) // 数组的最大值是: 55console.log(`数组的最小值是: ${newArr[1]}`) // 数组的最小值是: 3</script>
</body></html>

五、函数细节补充

两个相同的函数后面的会覆盖前面的函数
在Javascript中 实参的个数和形参的个数可以不一致

  • 如果形参过多 会自动填上undefined (了解即可)
  • 如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参)

函数一旦碰到return就不会在往下执行了 函数的结束用return

<!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>
</head><body><script>// function getSum(x, y) {//   return x + y//   // 返回值返回给了谁? 函数的调用者  getSum(1, 2)//   // getSum(1, 2) = 3// }// // let result = getSum(1, 2) = 3// // let num = parseInt('12px')// let result = getSum(1, 2)// console.log(result)// 1. 函数名相同, 后面覆盖前面// function fn() {//   console.log(1)// }// function fn() {//   console.log(2)// }// fn()// 2. 参数不匹配function fn(a, b) {console.log(a + b)}// (1). 实参多余形参   剩余的实参不参与运算// fn(1, 2, 3)// (2). 实参少于形参   剩余的实参不参与运算fn(1)   // 1 + undefined  = NaN </script>
</body></html>

1. 逻辑中断

开发中,还会见到以下的写法:
【函数】JavaScript 全栈体系(七)

  • 短路:只存在于 && 和 || 中,当满足一定条件会让右边代码不执行
  • 原因:通过左边能得到整个式子的结果,因此没必要再判断右边
  • 运算结果:无论 && 还是 || ,运算结果都是最后被执行的表达式值,一般用在变量赋值

2. 转换为Boolean型

2.1 显式转换:

‘’、0、undefined、null、false、NaN 转换为布尔值后都是false, 其余则为 true

【函数】JavaScript 全栈体系(七)

2.2 隐式转换:
  • 有字符串的加法 “” + 1 ,结果是 “1”
  • 减法 - (像大多数数学运算一样)只能用于数字,它会使空字符串 “” 转换为 0
  • null 经过数字转换之后会变为 0
  • undefined 经过数字转换之后会变为 NaN

【函数】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>
</head><body><script>console.log(Boolean('pink')) 	// trueconsole.log(Boolean(''))	 	// falseconsole.log(Boolean(0))		 	// falseconsole.log(Boolean(90))	 	// trueconsole.log(Boolean(-1))	 	// trueconsole.log(Boolean(undefined))	// falseconsole.log(Boolean(null))		// falseconsole.log(Boolean(NaN))		// falseconsole.log('--------------------------')let ageif (age) {console.log(11)}</script>
</body></html>

六、作用域

通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。

1. 全局作用域

作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件

处于全局作用域内的变量,称为全局变量

2. 局部作用域

作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。

处于局部作用域内的变量称为局部变量

如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐

但是有一种情况,函数内部的形参可以看做是局部变量。

<!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>
</head><body><script>let num = 10  // 1. 全局变量console.log(num) // 10function fn() {console.log(num) // 10}fn()// 2. 局部变量function fun() {let str = 'pink'}console.log(str)  // 错误</script>
</body></html>

七、匿名函数

函数可以分为具名函数和匿名函数

匿名函数:没有名字的函数,无法直接使用。

1. 函数表达式

// 声明
let fn = function() { console.log('函数表达式')
}
// 调用
fn()
<!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>
</head><body><script>// console.log(num)// let num = 10// 3 + 4// num = 10// 1. 函数表达式fn(1, 2)  //错误let fn = function (x, y) {// console.log('我是函数表达式')console.log(x + y)}// 函数表达式和 具名函数的不同   function fn() {}// 1. 具名函数的调用可以写到任何位置// 2. 函数表达式,必须先声明函数表达式,后调用// function fun() {//   console.log(1)// }// fun()</script>
</body></html>

2. 立即执行函数

场景介绍: 避免全局变量之间的污染

(function(){ xxx  })();
(function(){xxxx}());

注意: 多个立即执行函数要用 ; 隔开,要不然会报错

无需调用,立即执行,其实本质已经调用了

多个立即执行函数之间用分号隔开

第十四章 综合案例:转换时间

需求: 用户输入秒数,可以自动转换为时分秒

【函数】JavaScript 全栈体系(七)
分析:
①: 用户输入总秒数 (注意默认值)
②:计算时分秒(封装函数) 里面包含数字补0
③:打印输出

计算公式:计算时分秒
小时: h = parseInt(总秒数 / 60 / 60 % 24)
分钟: m = parseInt(总秒数 / 60 % 60 )
秒数: s = parseInt(总秒数 % 60)

<!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>
</head><body><script>// age = age + 1// 1. 用户输入let second = +prompt('请输入秒数:')// 2.封装函数function getTime(t) {// console.log(t)  // 总的秒数// 3. 转换// 小时:  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 : s// console.log(h, m, s)return `转换完毕之后是${h}小时${m}${s}`}let str = getTime(second)document.write(str)console.log(h)</script>
</body></html>