文章目录
JavaScript 基础 - 第4天
2023年2月7日 14点51分
函数
1声明和调用
函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。
声明(定义)
- function 函数名(){ 函数体}
- 声明(定义)一个完整函数包括关键字、函数名、形式参数、函数体、返回值5个部分
调用
- 函数名()
- 声明(定义)的函数必须调用才会真正被执行,使用
()
调用函数。不调用不会被执行
<script>
// 声明(定义)了最简单的函数,既没有形式参数,也没有返回值
function sayHi() {
console.log('嗨~')
}
// 函数调用,这些函数体内的代码逻辑会被执行
// 函数名()
sayHi()
// 可以重复被调用,多少次都可以
sayHi()
</script>
注:函数名的命名规则与变量是一致的,并且尽量保证函数名的语义。
小案例: 小星星
<script>
// 函数声明
function sayHi() {
// document.write('hai~')
document.write(`*<br>`)
document.write(`**<br>`)
document.write(`***<br>`)
document.write(`****<br>`)
document.write(`*****<br>`)
document.write(`******<br>`)
document.write(`*******<br>`)
document.write(`********<br>`)
document.write(`*********<br>`)
}
// 函数调用
sayHi()
sayHi()
sayHi()
sayHi()
sayHi()
</script>
2参数
通过向函数传递参数,可以让函数更加灵活多变,参数可以理解成是一个变量。
声明(定义)一个功能为打招呼的函数
- 传入数据列表
- 声明这个函数需要传入几个数据
- 多个数据用逗号隔开
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JavaScript 基础 - 函数参数</title>
</head>
<body>
<script>
// 声明(定义)一个功能为打招呼的函数
// function sayHi() {
// console.log('嗨~')
// }
// 调用函数
// sayHi()
// 这个函数似乎没有什么价值,除非能够向不同的人打招呼
// 这就需要借助参数来实现了
function sayHi(name) {
// 参数 name 可以被理解成是一个变量
console.log(name)
console.log('嗨~' + name)
}
// 调用 sayHi 函数,括号中多了 '小明'
// 这时相当于为参数 name 赋值了
sayHi('小明')// 结果为 小明
// 再次调用 sayHi 函数,括号中多了 '小红'
// 这时相当于为参数 name 赋值了
sayHi('小红') // 结果为 小红
</script>
</body>
</html>
总结:
- 声明(定义)函数时的形参没有数量限制,当有多个形参时使用
,
分隔 - 调用函数传递的实参要与形参的顺序一致
形参和实参
-
形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
-
实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
-
形参可以理解为是在这个函数内声明的变量(比如 num1 = 10)
-
实参可以理解为是给这个变量赋值
-
开发中尽量保持形参和实参个数一致
<script>
// 声明(定义)一个计算任意两数字和的函数
// 形参 x 和 y 分别表示任意两个数字,它们是两个变量 ,函数内部的型参不需要声明
function count(x, y) {
console.log(x + y);
}
// 调用函数,传入两个具体的数字做为实参
// 此时 10 赋值给了形参 x
// 此时 5 赋值给了形参 y
count(10, 5); // 结果为 15
</script>
函数参数默认值
//默认函数参数值写法1
function sum(a = 0 ,b= 0){
document.write(a+b)
}
sum()//忘记给函数实参 , 增强函数的健壮性 , 形参赋值 0 ,没有实参 自动调用 0
sum(1,2) //如果有参数 ,默认的形参 0 不会被执行
//默认函数参数值写法2(逻辑中断)
<script>
function fn(x, y) {
x = x || 0
y = y || 0
console.log(x + y)
}
fn(1,2)
</script>
补充细节
- 如果形参传递的是数组的,则声明函数是直接数组名即可 function ( arr=[] ){}
- 函数的实参可以是变量 变量可以来用户自己的输入
3返回值
函数的本质是封装(包裹),函数体内的逻辑执行完毕后,要想获得函数内部逻辑的执行结果,需要通过 return
这个关键字,将内部执行结果传递到函数外部,这个被传递到外部的结果就是返回值。
<script>
// 定义求和函数
function count(a, b) {
let s = a + b
// s 即为 a + b 的结果
// 通过 return 将 s 传递到外部
return s
}
// 调用函数,如果一个函数有返回值
// 那么可将这个返回值赋值给外部的任意变量
let total = count(5, 12) //相当于连两周步骤 count(5,12)=s; total=count(5,12)
</script>
总结:
- 在函数体中使用return 关键字能将内部的执行结果交给函数外部使用
- 函数内部只能出现1 次 return,并且 return 下一行代码不会再被执行,所以return 后面的数据不要换行写
- return会立即结束当前函数
- 函数可以没有return,例如alert,这种情况默认返回值为 undefined
4作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
全局作用域
作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
处于全局作用域内的变量,称为 全局变量
局部作用域
作用于函数内的代码环境,就是局部作用域。 因为跟函数有关系,所以也称为函数作用域。
处于局部作用域内的变量称为 局部变量
注意
如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
函数内部的形参可以看做是局部变量。
变量的访问原则 就近原则
let num = 10 function fn() { let num = 20 function fun() { let num = 30 console.log(num) } fun() } fn() //30 先从当前的作用域查找,如若没有,往上一层一层 走 (先布局再全局) function f1(){ let num = 123 function f2(){ let num = 0 console.log(num); } f2() } let num = 456 f1() // 0
5、匿名函数
函数可以分为具名函数和匿名函数
匿名函数:没有名字的函数,无法直接使用。 使用方法如下
函数表达式
将函数赋值给变量实现调用
函数表达式 必须是声明在前 调用再后 具名函数 可以再任何位置调用
// 声明
let fn = function() {
console.log('函数表达式')
}
// 调用
fn()
// 声明2
let fn = function( x , y) {
return x+y
}
// 调用2
fn(1,2)
立即执行函数
-
避免全部变量的污染
-
无需调用,立即执行,其实本质已经调用了
-
多个立即执行函数之间用分号隔开
-
在能够访问到的情况下 先局部 局部没有在找全局
//写法1
(function(){
xxx })();
()()--->(function(){
})()--->本质。括号1 ,是函数 括号2 是调用
(function(x ,y){
//形参
console.log(return x+y)
}
)(1,2);//实参
//写法2
( ())--->(function(){
xxxx}());
(function(x ,y){
//形参
console.log(return x+y)
}(1,2))//实参
6 函数细节补充
-
两个相同的函数,后边的函数会覆盖前面的函数 就近原则
-
js中实参的个数 可以和形参的个数不一样
-
实参多余形参个数 多余的传不过去,不参与运算 (函数内部的arguments ,装着所有的实参)
-
实参小于形参个数 形参缺少的默认是 undefined
-
7.逻辑中断
存在与 && 与 | | 之间 ,
一真一假 假与真 看前边的一半 后续不再执行
两个都是真值 && 输出最后一个 || 输出第一个
<script>
function fn(x, y) {
x = x || 0
y = y || 0
console.log(x + y)
}
fn(1,2)
</script>
8.转换为Boolean值
console.log(Boolean('pink'))
console.log(Boolean('')) //false
console.log(Boolean(0)) //false
console.log(Boolean(90))
console.log(Boolean(-1))
console.log(Boolean(undefined)) //false
console.log(Boolean(null)) //false
console.log(Boolean(NaN)) //false
9 综合案例
封装时间函数案例
<script>
let time = +prompt('输入索要计算的秒数')
function getsecond(t) {
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 (`${
time}秒转为时分秒 依次为 ${
h}${
m}${
s} `)
}
let str = getsecond(time)
console.log(str);
</script>