js笔记9-函数

一.函数的理解

从英文的角度来看,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-数组

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值