tips
1-undefined+任意类型(除了字符串,字符串会拼接)=NaN
2-声明了但是没有赋值或没有值的东西,如变量,数组,没有设置return值的函数 等,打印输出的是undefined
3-数字类型可以直接输出,但是英文的话会被认为是变量,如果没有声明就会报错。
4-Shift+Alt+鼠标左键可以同时选择多行操作
为什么学习函数
函数的使用
命名
函数的执行
函数只封装不会被执行,必须被调用才会被执行
alert()和parseInt()也是函数的调用,只是环境中已经提前帮我们封装好了
函数传参
调用中写的值是实际参与运算叫实参,function name(形参){},
形参相当于在函数体内声明了的东西(实参是一个变量它就是变量,实参是数组,它就算数组等等)
多个参数之间用逗号隔开,尽量做到形参和实参数量相同,如果实参多于形参,则前面的生效,后面的会存储在一个argument的伪数组中(有长度,但是不能pop,push等)
这个arguments在此函数内,在函数外用arguments是没有被声明的,这也很好理解,因为一个页面有很多个函数,不可能共用arguments
利用逻辑中断,防止无实参传入,导致结果为undefined
如图,当无实参,用或运算,就会把结果赋值为0
案例
<script>
let sum = 0
function getSum(arry){
for(i=0;i<arry.length;i++){
sum+=arry[i]
}
}
getSum([100,99,92])
document.write(sum)
</script>
函数返回值
函数有的有返回值,有的没有返回值。
有的函数除了处理完问题,应该还需要有返回值,就像厨师炒了菜,要返回出来给顾客吃,不能把菜烂在厨房,如pop()返回删除的元素值,unshift()返回新数组的长度,promt()返回用户输入的字符串等等。
有的函数没有,如alert()它的作用就是一个警示框,不需要返回值。
那么返回值怎么返回呢?
使用return返回,且一个函数体内语句,执行return后,直接退出函数体,不再执行后续代码。
注意
这个函数虽然返回值和那一句document.write()毫不相干,但是因为有 let re = getSum([100,99,92])这一句
就等于函数被调用了,函数内的所有语句等于被执行了一遍。
返回数组最大值
<script>
function getSum(arry) {
let max = arry[0]
for (let i = 0; i < arry.length; i++) {
if (max <= arry[i + 1]) {
max = arry[i + 1]
}
}
document.write(`最大值为${max}`)
return max
}
// 你搁着重复声明呢?作用域不同,不冲突的。
let max = getSum([100, 99, 92,99999])
</script>
函数返回多个值
1-return只能返回一个值,强行返回多个,取最后那一个。
那我咋返回多个值呢
答:使用数组的形式返回出来,虽然返回的只有一个数组,但是可以有多个各种不同的数据。
<script>
function manyDdata (x,y){
jia=x+y
jian=x-y
cheng=x*y
return [jia,jian,cheng]
}
manyDdata(1,2)
document.write(manyDdata(1,2))
</script>
三元表达式是有一个返回值的,如下图
断点调试的f10与f11区别
f10对应半圆箭头的快捷键,遇到函数,直接完成进行下一条语句
f11对应向下箭头的快捷键,遇到函数,会进入函数内部,分析函数内部的语句执行过程。
作用域
为什么我明明声明了变量,却用不了呢?
因为第一个是在for循环内声明的,for循环是块作用域,第二个num2是在函数内声明的,有函数作用域。
怎么简单区分到底能不能用?
一句话,被包含的能用包含它的,爹的儿子用,儿子的爹不能用。
为啥我随便用,没有这啥作用域的讲究?
1-你用的声明变量的关键词是var,var有变量提升,不规范现在一般不使用。
2-如下图你根本没声明,直接使用了变量并赋值,那么这个变量会被当做全局变量,不建议使用,底层会有漏洞。
Tips
1-函数中的形参可以看作是被声明了的一个具有函数作用域的局部变量
2-global全局,local局部的,block块
作用域的概述
注意如果有两个script标签,它们定义的变量一样是全局的
如下,第一个标签内声明的变量,第二个script里面是可以用的。
<script>
let a = 2, b = 3
</script>
<script>
document.write(a)
</script>
两个作用域声明了名字一样的变量,调用者在同时两个作用域内,到底执行谁呢?按照什么规则执行的?
上图中,函数作用域的num和for块作用域的num都可以被console.log使用,那么使用谁?
通过作用域链,简单来说就近原则,可以知道,执行的结果为20
匿名函数
一般将匿名函数赋值给一个变量,并通过变量名称来调用,是高阶函数(包含函数表达式和回调函数)的一种,也叫函数表达式。
默认这个变量名称就是它的函数名了。
使用场景
点击了这个按钮后,就会执行这个函数。(这种是老的写法,新写法是添加监听器)
立即执行函数
一般函数不调用不会执行,但是这个函数可以立即执行。
第一种写法
其实立即执行函数写出来,就已经等于调用了,如上图
匿名函数的变量fn就等价于function(){}
而立即执行函数是(function(){}) ()就等于fn(),其中xy是形参,1和2是实参。
第二种写法
一种是把匿名函数的变量fn就等价于function(){},把这个fn用小括号包起来,就等于(fn)()
第二种写法是不包fn,把整个包起来,等于(fn ())
如上图,立即执行函数写了一个函数名,其实立即执行执行函数和匿名函数也是可以写一个”假名字”的,用来区分它的作用。
使用场景
立即执行函数,不是为了复用,被反复调用,而是为了让这段js按顺序运行,但是怕写的变量和其他变量冲突,就有了立即执行函数,因为在函数内,变量的作用域不同,就不用担心变量冲突变量污染了。
注意
如果一个页面有多个立即执行函数,不想其他语句分号;可以省略(编辑器内换行等于分号),但立即执行函数一定要在函数后面加分号,否则会报错,为了防止上一个立即函数后面没写分号,通常在立即执行函数前再加一个分号。
这个分号不一定是立即执行函数的,但反正两个立即执行函数间的语句,至少有一个分号; 去隔开它们就行了。
<script>
(function hah(){
document.write(1)
}())
let num =2;
(function hah(){
document.write(2)
}())
</script>
这里用一个普通的let声明,后面有分号也行。
输入秒数转换为时分秒案例
<script>
// 用户输入秒数
let seconds =prompt(`请输入秒数`)
// 封装转换函数
function getResult (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 `计算后的时间为${h}小时${m}分${s}秒`
}
// 打印输出
let result =getResult(seconds)
document.write(result)
</script>
遇到错误
1-三元表达式是返回一个值,但我并没有给这个返回值去赋予变量。
2-形参就相当于函数内声明的一个变量,不能再次声明