日期:2023-03-30 学习目标:理解封装的意义,能够通过函数的声明实现逻辑的封装,知道对象数据类型的特征,结合数学对象实现简单计算功能。
函数(function)
函数(function)是被设计为执行特定任务的代码块 可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是精简代码方便复用。
比如 alert()、 prompt() 和 console.log() 都是一些 js 已经封装好了de 函数,可以直接调用
函数的声明和调用
函数的声明
一个完整函数包括关键字、函数名、形式参数、函数体、返回值5个部分
function 函数名(形式参数) {
函数体
}
![[函数声明.jpg]]
注意:
- 形参可以没有,可以有多个
- 函数命名方法和变量命名基本一致,尽量小驼峰式命名法,前缀应该尽量为动词
- 声明(定义)的函数必须调用才会真正被执行
函数的调用
函数声明后不会立即执行,会在我们需要的时候调用到,调用方法:
//声明函数
function 函数名(形式参数) {
函数体
}
//调用函数
函数名();
例:
function sayHi() {
console.log('嗨~')
}
sayHi()
函数的参数
参数表示函数运行的未知条件,需要调用者告知的数据,通过向函数传递参数,可以让函数更加灵活多变
形参和实参
形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数) 实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数) 形参可以理解为是在这个函数内声明的变量,实参可以理解为是给这个变量赋值
开发中尽量保持形参和实参个数一致
函数传参
函数执行时,会将实参传递给形参,相当于将实参赋值给形参
函数参数总结
- 声明(定义)函数时的形参没有数量限制,当有多个形参时使用
,分隔 - 调用函数传递的实参要与形参的顺序一致
- 实参可以是数字、变量、数组甚至其他数据类型
一些例子:
//求累加和
function getSum(start, end) { // start、end即为形参
let sum = 0
for (let i = start; i <= end; i++) {
sum += i
}
document.write(sum)
}
getSum(1, 100) //1和100即为实参;实参为数字
//函数执行时,start = 1 ;end = 100
//求累加和:让用户决定的起始和终止值
function getSum(start, end) { // start、end即为形参
let sum = 0
for (let i = start; i <= end; i++) {
sum += i
}
document.write(sum)
}
let start = +prompt('请输入起始值:')
let end = +prompt('请输入结束值:')
// 调用函数
getSum(start, end) // 实参为变量
//数组求和
function getArrSum(arr = []) {
let sum = 0
for (let i = 0; i < arr.length; i++) {
sum += arr[i]
}
console.log(sum)
}
getArrSum([1, 2, 3, 4, 5]) // 实参为数组
getArrSum([11, 22, 33])
getArrSum()
参数默认值: 形参的默认值为 undefined ,通常在声明函数时赋予形参一个默认值,使程序更为严谨
函数的返回值
函数的本质是封装(包裹),函数体内的逻辑执行完毕后,执行结果需要通过 return 关键字,将内部执行结果传递到函数外部,这个被传递到外部的结果就是返回值。
- 在函数体中使用return 关键字能将内部的执行结果交给函数外部使用
- return 会直接结束整个函数的运行, return 下一行代码不会被执行
- 如果函数中没有书写return,则该函数会在末尾自动return undefined。
例1:求和函数
function count(a, b) {
let sum = a + b
// s 即为 a + b 的结果
// 通过 return 将 s 传递到外部
return sum
}
// 调用函数,如果一个函数有返回值
// 那么可将这个返回值赋值给外部的任意变量
let total = count(5, 12)
例2:判断一个数是不是奇数
function isOdd(n) {
if (n % 2 === 0) {
return false; // 返回false
}
return true; // 返回true
}
isOdd(6) //返回值为false,相当于 isOdd(6) = false
例3:求最大/最小值
function getMax(arr = []) {
let max = arr[0]
for (let i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i]
}
}
return max
}
function getMin(arr = []) {
let min = arr[0]
for (let i = 1; i < arr.length; i++) {
if (min > arr[i]) {
min = arr[i]
}
}
return min
}
getMin([1, 2, 3, -1, 5]) //返回值为 -1
getMax([1, 2, 3, 4, 6]) //返回值为 6
//使用数组返回多个值
function getValue(arr = []) {
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 [max,min] //使用数组可以返回多个值
}
getValue([1,5,9,10,30,99]) //返回值为 [99,1]
函数的一些细节:
- 两个相同的函数后面的会覆盖前面的函数
- 在Javascript中 实参的个数和形参的个数可以不一致 如果形参过多 会自动填上undefined (了解即可) 如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参)
- 函数一旦碰到return就不会在往下执行了 函数的结束用return
作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
只要是代码,就至少有一个作用域
全局作用域
作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
处于全局作用域内的变量,称为全局变量
局部作用域
作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。
处于局部作用域内的变量称为局部变量
如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
两种需要注意的情况:
- 如果在函数内部,变量没有声明而直接赋值,也可以当全局变量看,但不推荐如此使用
- 函数内部的形参可以看做是局部变量。
变量访问原则
变量在访问时采取就近原则的方式来查找变量最终的值,在能够访问到的情况下,先访问局部,局部没有再访问全局
匿名函数
函数可以分为具名函数和匿名函数
匿名函数:没有名字的函数,无法直接使用。可以通过函数表达式和立即执行函数来使用
函数表达式
// 声明
let fn = function() {
console.log('函数表达式')
}
// 调用
fn()
必须先声明后调用
立即执行函数
//两种方式
(function(){ 函数体 })();
(function(){ 函数体 }());
立即执行函数的作用:防止全局变量污染
无需调用,立即执行,其实本质已经调用了
多个立即执行函数之间必须用分号隔开
具名函数同样可以通过函数表达式和立即执行函数来使用
函数案例
//将输入的秒数转换为时分秒
let second = +prompt(`请输入秒数:`)
function getTime(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 : h
m = m < 10 ? '0' + m : m
s = s < 10 ? '0' + s : s
return `${t}秒转换后是:${h}时${m}分${s}秒`
}
let str = getTime(second)
document.write(str)
//或者直接写成:document.write(getTime(second))