文章目录
一.函数的理解
从英文的角度来看,function是函数、功能的意思。
函数:将某一个常用的功能进行封装。
我们要使用此功能的时候,就可以调用此函数。
例如,提示框的功能就是一个函数,它的功能是输入数据。
封装的例子:冬天的时候,我们会把很多菜放在冰箱里,方便自己不用每天买菜。
二.函数的使用
在JavaScript语言中,函数分为2种,第1种是关键字function定义的函数,第2种是表达式形式的函数。
函数的使用分为2部分:① 声明 ② 调用
<script>
function fun(){ //函数声明
console.log("学习"); //代码书写的地方
}
fun(); //函数调用
fun(); //函数再次调用
</script>
总结:函数可以多次调用。
在js中,函数属于引用类型的数据。
利用关键字typeof去检测函数的类型
<script>
function fun(){ //函数声明
console.log("学习"); //代码书写的地方
}
fun(); //函数调用
console.log(typeof fun);
</script>
总结:虽然typeof检测出来的类型是function,但是,它是属于object类型的。原因:在js语言中是没有function类型的。
总结:如果不调用函数的声明,那么函数体中的代码块是不会执行的。
三.函数的形参和实参
形参:形式上的参数,没有具体的值。
在函数声明的时候,声明部分的小括号里可以书写形参。
实参:实际上的参数,是有具体的值。
在函数调用的时候,调用部分的小括号里可以书写实参。
<script>
function fun(a,b){ //形参
//当形参有了值之后,就可以打印数据了
console.log(a);
console.log(b);
}
fun(2,3); //在调用函数的时候,将实参传递给形参
//并且按照顺序依次赋值,先是2赋值给a,再把3赋值给b
</script>
总结
调用函数的时候,是将数据传递给形参,只有这样,形参才能得到值。接着,函数才能使用这个值。
调用函数的时候,会将实参按照顺序依次赋值给形参。
<script>
function fun(a,b,c){
console.log(a);
console.log(b);
console.log(c); // c没有得到值,所以返回了一个undefined
}
fun("学习",true);
</script>
注意事项:在js函数中,传值的时候,变量是不需要用var去声明的。参数之间是要用逗号隔开的。声明函数的小括号里是2个变量,调用函数的小括号里是2个变量的值,这个值可以是任意类型的数据。
总结:形参的个数不能决定实参的个数,实参的个数也不能决定形参的个数。
四.变量
局部变量
局部变量:只能在函数体中使用。
两种情况
①变量作为函数形参
<script>
function isEven(num){
if(num%2==0){
console.log(num+"是偶数"); //num是局部变量,可以在函数体内使用
}
else{
console.log(num+"是奇数");
}
}
isEven(66);
isEven(67);
//num放在这里使用会报错,因为函数体外的变量叫做全局变量。
//num不可以放在函数体外去使用。
</script>
②变量在函数体中声明
<script>
function isEven(num){
if(num%2==0){
console.log(num+"是偶数"); //num是局部变量,可以在函数体内使用
}
else{
console.log(num+"是奇数");
}
//变量在函数体中声明
var a=100;
var b=200;
console.log(a+b);
}
isEven(66);
isEven(67);
</script>
问题:为什么会打印两次300?因为函数被调用了2次。
总结:在函数体内声明的变量叫做局部变量。
全局变量
全局变量:可以在js行为层当中的任意地方进行使用,相当于在函数体外进行活动的。
在条件语句中的运用
<script>
if(true){
var num=1;
console.log(num); //if语句内可以打印
}
console.log(num); //if语句外也能打印
//所以,num是全局变量
</script>
在循环中的运用
<script>
for(var i=0;i<4;i++){
console.log(i); //循环内打印
}
console.log("我是循环外部"+i); //循环外也能打印
//所以,i是全局变量
</script>
在函数中的运用
<script>
//全局变量是放在函数体外的,当函数需要这个声明的时候,就会去用它。
var a=1;
function fun(){
console.log(a);
}
fun();
</script>
五.作用域
知识点
scope:作用域
作用域:书写代码的范围。
全局作用域:它最大的范围是在写在script标签里的,但是它是在函数体外的。
局部作用域:它是在函数体内的。
总结:当局部作用域中,访问不到变量的时候,就会去全局作用域中找一下有没有合适的变量,如果找到了,就会拿借来使用一下。
图形理解
六.作用域的经典面试题
第一题:使用了局部作用域中的局部变量
<script>
var num=66;
//声明关键字形式函数
function fun(){
var num=77;
console.log(num); //77
}
fun();
</script>
函数会往上找局部变量,如果找到了,就会打印。
第二题:变量声明部分提升,会提升到局部作用域的最上方
<script>
var num=66;
//声明关键字形式函数
function fun(){
console.log(num); //undefined
var num=77;
}
fun();
</script>
变量声明的提升:var num提升到了局部作用域的最上方,但是赋值部分没有提升,所以,提升后的变量没有值,接着,控制台就返回了一个undefined,是未定义的意思。
图形理解
第三题:任何语句都无法阻挡变量声明的提升
<script>
var num=66;
//声明关键字形式函数
function fun(){
console.log(num);
if(false){ //不执行
var num=77; //undefined
}
}
fun();
//总结:任何语句都无法阻挡变量声明的提升,并且会提升到当前作用域的最上方。
</script>
虽然变量声明在if语句里,但是,终究无法阻挡变量声明的提升。
七.return关键字
return:返回
return是与函数一起搭配使用的,并且return只能出现在函数体内。
作用
① return之后的语句不再执行。
<script>
function str(){
console.log("学习"); //学习
return; //return之后的语句不再执行。
console.log("快乐"); //无法打印
}
str();
</script>
② 可以将函数计算完的结果返回,并且函数体外也可以获取到函数的返回结果。
写法1:局部变量result去获取函数的数据
<script>
function str(a){
var a=10;
return a;
}
var result=str();
console.log(result); //10
</script>
写法2:实参传递给形参,利用形参去返回结果
<script>
function str(a){
console.log(a); //10
return a; //将函数体中的数据(计算完的结果)返回给函数体外。
console.log(a); //无法打印
}
str(10);
</script>
总结
①return后面可以跟任意类型的数据。
②函数体外可以获取到函数返回的结果。
③代码分析:return与传递数据写在了一起,需要自己去区别,并理解。
<script>
function str(a){
console.log(a); //10
return a;
console.log(a); //无法打印
}
//全局变量获取了函数的值,因为函数有打印功能,所以结果为10
var result=str(10);
console.log(result); //打印全局变量,结果也为10
</script>
八.函数实战
封装一个函数:函数功能是计算两数之和。
写法1:传递数据的方法。
<script>
function fun(a,b){
console.log(a+b); //30
}
fun(10,20);
</script>
写法2:用return获取数据的方法。
<script>
function fun(){
var a=10;
var b=20;
return a+b;
}
var result=fun();
console.log(result); //30
</script>
水仙花数
打印100-999之间的水仙花数
<script>
function fun(num){
var ge=num%10;
var shi=parseInt((num/10)%10);
var bai=parseInt((num/100)%10);
if(num==Math.pow(ge,3)+Math.pow(shi,3)+Math.pow(bai,3)){
return true;
}
else{
return false;
}
}
for(var n=100;n<=999;n++){
var bol=fun(n);
if(bol){
console.log(n+"是水仙花数");
}
}
</script>
完美约数
完美约数:该数的约数和等于本身。
约数:相当于因数,能被整除的数是约数。
例如,6的约数有1,2,3,6
但是,完美约数是不可以包含本身的。所以是1+2+3=6
<script>
function isPerfect(num){
var sum=0;
for(var i=1;i<num;i++){
if(num%i==0){
sum=sum+i;
}
}
if(num==sum){
return true;
}
else{
return false;
}
}
for(var n=1;n<=100;n++){
var bol=isPerfect(n);
if(bol){
console.log(n+"是完美约数");
}
}
</script>
解决思路:利用一个累加器的思想,让一个数的因数开始累加,累加之后的和等于该数的本身,那就是完美约数了。
问题1:为什么是num%i
原因:假设我们对6进行约数判断。如果要得到正确的因数,就应该从6/1开始。这种情况下,传进来的num是6,而i是从1开始的。
九.表达式形式的函数
表达式形式的函数:将function定义的函数赋值给变量的形式。
<script>
var str=function fun(){
console.log("学习");
}
str(); //调用函数
console.log(str); //打印函数
</script>
注意事项:函数赋值给了变量str,所以调用的时候,名字就不在是函数名,而是变量名+小括号。
十.匿名函数
匿名函数:没有名字的函数。
<script>
var str=function (){
console.log("学习");
}
str();
console.log(str); //打印函数
</script>
从运行效果可以看出,少了函数名。
十一.关键字形式的函数与表达式形式的函数的区别
功能一样:想用函数的时候,调用即可。
用法不一样:
表达式形式的函数:只能在声明后才能调用。
<script>
console.log(str); //undefined
var str=function (){
console.log("学习");
}
console.log(str); //打印函数
</script>
问题:为什么是undefined ?
原因:由于变量声明会提升到作用域的最上方,但是赋值部分是不会被提升的。所以,调用的时候没有获取到函数的数据,从而导致返回结果为undefined(未定义类型)。
图形理解:
总结:关键字形式的函数可以在声明之前或声明之后调用。
<script>
console.log(str);
function str(){
console.log("学习");
}
console.log(str);
</script>
十二.回调函数
CallBack:回调函数
概述:当一个函数执行的时候,传递实参是另外一个函数声明的部分。这个实参(函数)就可以被称为回调函数。
函数复习
<script>
//函数声明部分
function promise(a,b,CallBack){
console.log(a.random()); //变量a获取到了对象,就能使用对象里的方法
console.log(b); //打印数字
console.log(CallBack); //打印逻辑值true
}
//函数调用部分
promise(Math,2,true);
//我传入了一个Math对象、一个数字、一个逻辑值
</script>
回调函数案例1
<script>
//函数声明部分
function promise(a,b,CallBack){
console.log(a);
console.log(b);
console.log(CallBack);
}
//第三个值出现了回调函数的用法
promise(1,2,function(){
});
</script>
回调函数案例2
<script>
//函数声明部分
function promise(a,b,CallBack){
console.log(a);
console.log(b);
CallBack(); //调用回调函数
}
//第三个值出现了回调函数的用法
promise(1,2,function(){
console.log("执行回调函数");
});
</script>
结合以上案例,可以得出结论:回调的部分是实参,也是匿名函数,也是回调函数。
十三.函数递归
递归:函数直接或间接调用自身的现象。
<script>
function str(){ //声明
console.log("学习");
str(); //递归:函数自己调用自己
}
str(); //调用
</script>
思路:调用函数,执行函数体,在函数体中,又进行了函数调用自己的现象。相当于无限循环,永远不会停止。除非手动停止。
十四.IIFE
I: immediately ,立刻。
I:invoking ,调用。
F:function,函数。
E:express,表达式。
IIFE是立刻调用函数表达式的意思。
概述:在声明表达式形式函数的同时,马上执行1次。
<script>
var str = function(){ //声明表达式形式的函数时
console.log("学习");
}(); //立刻执行1次
</script>
当关键字形式的函数不能立即执行1次的时候,我们可以将关键字形式转换成表达式形式的函数。
方法1:用 “ + ” 去转换
<script>
+function str(){ //声明表达式形式的函数时
console.log("学习");
}(); //立刻执行1次
</script>
方法2:用 “ - ” 去转换
<script>
-function(){ //用减号转换,并且采用了匿名函数的写法
console.log("学习");
}(); //立刻执行1次
</script>
方法3:用 “ ! ” 去转换
<script>
!function(){
console.log("学习");
}(); //立刻执行1次
</script>
方法4:用小括号去转换
<script>
(function(){
console.log("学习");
})(); //立刻执行1次
</script>
总结:每一个IIFE都有属于自己独立的作用域,互不影响。
<script>
//总结:虽然他们的局部变量都是a,但是它们是互不影响的。
//所以,它们都有自己的局部作用域。
+function(a){
a+=2;
console.log(a);
}(10);
-function(a){
a+=3;
console.log(a);
}(20);
</script>
篇章
上一篇:js笔记8-循环案例
下一篇:js笔记10-数组