理解函数的封装特性,掌握函数的语法规则
目录
声明和调用
函数可以把具有相同或相似逻辑的代码“包裹”起来,通过函数调用执行这些被“包裹”的代码逻辑,这么做的优势是有利于精简代码方便复用。
声明(定义)
声明(定义)一个完整函数包括关键字、函数名、形式参数、函数体、返回值5个部分
调用
声明(定义)的函数必须调用才会真正被执行,使用 ()
调用函数。
<script>
//函数:就是一段代码块,代码块就是包裹在花括号里面的代码
//函数的作用:实现重复功能的代码复用,优化代码
//函数的使用方式:
//1.定义函数
function getAge(){
document.write('我的年纪是18岁')
}
//注意点:定义函数是不执行
//2.调用函数 函数名()
getAge()
</script>
小案例:
1.求两个数的和
<script>
function getSum(){
let num1 = 10
let num2 = 20
document.write(num1 + num2 )
}
getSum()
</script>
2.求1-100的和
<script>
function getSum(){
let sum = 0
for(let i = 1;i <= 100;i++){
sum += i
}
console.log(sum);
}
getSum()
</script>
参数
通过向函数传递参数,可以让函数更加灵活多变,参数可以理解成是一个变量。
声明(定义)一个功能为打招呼的函数
-
传入数据列表
-
声明这个函数需要传入几个数据
-
多个数据用逗号隔开
<script>
//参数的作用:通过函数灵活性
//需求:定义求和的函数,可以求任意2值的和
//1.声明求和函数,形参(也可以理解定义了一个变量)
function getSum(x,y){
console.log(x + y);
}
//2.调用这个函数,实参(也可以在给变量赋值)
// getSum(1,2)
getSum(100,50)
// getSum(1)
//注意点:
//1.形参和实参要对应,形参没有接收实参默认是undefined
//2.形参和实参如果定义多个,使用逗号隔开
//3.形参给实参传递过程,我们可以理解在给变量进行赋值
</script>
案例:
采用函数封装的形式:传递2个数,计算两者的和,打印到页面中
<script>
let num1 = +prompt('请输入第一个值')
let num2 = +prompt('请输入第二个值')
function getSum(x,y){
console.log(x + y);
// let a = x
// let b = y
// document.write(a + b);
}
getSum(num1,num2)
let a = 10
let b = a
console.log(b);//10
</script>
什么是默认参数?
答:调用函数时如果传递实参.给形参的默认值,称之默认参数
为什么有给函数参数添加默认参数?
答:让程序更加严谨,同时可以防止程序出错
<script>
function getSum(x,y){
console.log(x);
console.log(y);
console.log(x + y);
}
getSum()
</script>
案例:
需求:学生的分数是一个数组通过变量传递,封装一个计算每个学生的总分的函数
<script>
let aikun = [99,50,10,20,0]
//1.封装数组求和功能函数,数组有参数进行传递
//如果用户不传递参数,默认是undefined,但是undefined没有长度,代码会报错
// 解决方法:添加默认参数
function sumArray(Arr = []){
// console.log(Arr);
//1.1定义求和变量
let sum = 0
//1.2遍历数组进行累加
for(let i = 0; i < Arr.length; i++){
//sum = sum + Arr[i]
sum += Arr[i]
}
//1.3输出求和结果
console.log(sum);
}
//2.调用函数.传递数组
sumArray(aikun)
sumArray()
</script>
返回值
函数的本质是封装(包裹),函数体内的逻辑执行完毕后,函数外部如何获得函数内部的执行结果呢?要想获得函数内部逻辑的执行结果,需要通过 return
这个关键字,将内部执行结果传递到函数外部,这个被传递到外部的结果就是返回值。
<script>
//函数的返回值:函数是一个代码块,执行完特定任务之后会返回结果,结果需要返回给调用者,返回结果方式称之为返回值
//返回值的使用方法示例:
function fn(){
// return 结果
return 20
}
let val = fn() //此时返回的结果20先给fn()调用者,在调用赋值给val,相当于val存的结果20
console.log(val);// fn()=20
//返回的结果给谁?
//调用者fn()
let a = 10
let b = a
let c = b
console.log(c);//10
//注意:并不是所有的函数都有返回值,具体根据需求而定
//用户传递两个参数,定义一个求和的函数,返回结果在a标签和button标签输出求和的结果
// 1.定义一个求和函数,查看他的执行流程 形参
function getSum(x ,y){
// 结果返回出来
return x + y
}
// 2.调用函数 实参
// console.log(getSum(50,80));
let sum = getSum(5,5)
// 3.拿到结果之后不同标签进行渲染
document.write(`<a href='#'>${sum}</a><br>`)
document.write(`<button>${getSum(1,2)}</button>`)
//函数的执行流程:就是一次0交易的过程1.调用函数(传递参数)2.执行函数体(产生结果)3.return关键字返回结果(调用者)
</script>
<script>
//总结:返回值的3个细节
//1.返回值return可以把结果返回给调用者
//2.return后面,换行的代码不会执行
function fn(){
alert(2222)//换行
return 10
alert(111)//不执行
}
console.log(fn());
//3.不是所有的函数都有返回值,没有返回值的函数为undefined
function Alert(){
document.write('弹框执行了')
}
Alert()
console.log(Alert());//没有返回值,返回的undefined
</script>
案例:
1.定义一个函数,传递参数,求任意2个数中的最大值,并返回
<script>
//1.定义一个函数,传递参数,求任意2个数中的最大值,并返回
function getMax(x, y) {
// if(x>y){
// return x
// }else{
// return y
// }
// 表达式产生结果
return x > y ? x : y
}
let max = getMax(5, 20)
console.log(max);
</script>
2.定义一个函数,传递参数,求任意数组中的最大值并返回这个最大值
<script>
//1.定义求数组最大值函数 形参
function ArrMax(Arr) {
//console.log(Arr);
// 1.定义最大值变量,从数组里面挑一个默认是为最大值
let max = Arr[0]
//2.遍历数组,依次进行比较,找出最大值,重新赋值
for (let i = 0; i < Arr.length; i++) {
if (max < Arr[i]) {
max = Arr[i]
}
}
//返回值返回最大值
return max
}
//2.调用函数 实参
console.log(ArrMax([1, 2, 5, 8, 9]));
</script>
3.定义一个函数,传递参数,求任意数组中的最小值并返回这个最小值
<script>
//1.定义求数组最小值函数 形参
function ArrMin(Arr) {
//console.log(Arr);
// 1.定义最小值变量,从数组里面挑一个默认是为最小值
let min = Arr[0]
//2.遍历数组,依次进行比较,找出最小值,重新赋值
for (let i = 0; i < Arr.length; i++) {
if (min > Arr[i]) {
min = Arr[i]
}
}
//返回值返回最小值 返回值如果需要返回多个值可以存放在数组,再返回,
return min
}
//2.调用函数 实参
console.log(ArrMin([1, 2, 5, 8, 9]));
</script>
函数的细节补充
1.相同函数之间会覆盖
<script>
function fn() {
return 111
}
function fn() {
return 222
}
console.log(fn());
</script>
2.函数的参数不一致的问题
2.1函数的形参多余实参
<script>
function handle(a, b, c, d) {
console.log(a, b, c, d);//多余形参默认是undefined
}
handle(1, 2, 3)
</script>
2.2函数的实参多余形参, 函数的实参对于形参存放在伪数组arguments,后期递归使用
<script>
function handle(a, b) {
console.log(arguments);//函数内部存储实参在arguments,伪数组
console.log(a, b);//多余实参放伪数组arguments
}
handle(1, 2, 3, 4, 5)
</script>
3.return代表函数运行结束,后面的代码不执行
<script>
function hi() {
console.log(111);
return //return代表函数运行结束
console.log(222);
}
hi()
</script>
作用域
通常来说,一段程序代码中所用到的名字并不总是有效和可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。
全局作用域
作用于所有代码执行的环境(整个 script 标签内部)或者一个独立的 js 文件
处于全局作用域内的变量,称为全局变量
1.全局作用域(全局变量) 生效范围(整个js文件整个script标签内)
局部作用域
局部作用域(局部变量,函数作用域) 生效范围(函数内部)
如果函数内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
特殊情况:但是有一种情况,函数内部的形参可以看做是局部变量。
块级作用域
块级作用域 (块级变量)只能在循环或者判断语句使用let定义的变量或者const定义的常量,只能在花括号中生效
作用域链:
作用域链: :变量在作用域中的查找过程,我们称之为作用域链
作用域链的访问规则:就近原则,逐级往上查找
逻辑中断:
<script>
// 逻辑与 找假 短路后面不执行 返回第一个为假的条件,简称为后面的逻辑进行短路(代码不执行)
console.log(11 && false);//false
console.log(22 && 33 && 44);//44
// 逻辑或 找真 返回第一个为真的条件,后面的逻辑进行短路,不执行
console.log(true || 'abc' || false);//true
console.log(0 || '' || NaN);//NaN
// 函数有一个默认参数 es6推出来
/* function fn(x = 0, y = 0) {
return x + y
}
console.log(fn());//0 */
// es5的函数默认参数
function fn(x, y) {
// console.log(x + y);//NaN
x = x || 0
y = y || 0
console.log(x,y);//0 0
// return x + y
}
// fn()
fn(1,2)
//逻辑短路:就是通过逻辑与(找假)和逻辑或(找真),如果第一个值满足条件,后面代码不执行,如果全部不满足条件,返回最后一个
</script>