JavaScript学习笔记(四):函数和递归

0 目录

  • 函数的声明
  • 函数表达式
  • 函数的组成形式
  • JavaScript不限制参数个数
  • 作用域
  • 递归

1 函数的声明

函数的声明和变量的声明类似,是使用function关键字后接函数名

function fun(a){
    a = a + 2;
    return a;
}

上述示例中,fun是函数名,它后面有一个括号,是用来放参数的;括号里的a就是函数的参数,它可以被函数内部的代码所使用;结尾的return是一个关键字,是用来向函数的调用者返回一个值的。
函数的调用方式:若要调用上述的函数,直接输入函数名加括号及参数即可,如fun(2);,调用的结果就是计算2+2的值,结果返回数字4

2 函数表达式

形如function(){}的代码就是函数表达式,可用于声明函数,因为这个函数没有函数名,所以也被叫做"匿名表达式",用法如:

var func = function(){
    //代码段...
}

这样子声明的函数,调用时的函数名由变量名func代替,如:func();

3 函数的组成形式

函数一般包含三部分:

  • 函数名称(必须要有)
  • 参数(可有可无)
  • 函数体(必须要有)

其中,参数分为"形参"和"实参","形参"是函数声明时产生的一个局部变量,而"实参"是调用函数时,传给函数的一个实际值

4 JavaScript不限制参数个数

JavaScript的函数的参数,声明时的形参个数和调用时的实参个数可以不一致,如:

function func1(a, b){
    //do somethings
}
func1(1, 2, 3); //允许调用时的实参个数比声明时的形参个数多,不会报错

function func2(a, b, c){
    //do somethings
}
func2(1, 2);    //允许调用时的实参个数比声明时的形参个数少,可能会报错

当实参的个数比形参的个数多时,多出来的实参将被隐式地存储在实参列表里,不会导致报错。关于这个实参列表,后面再介绍。

当实参的个数比形参的个数少时,多出来的形参会被赋值为undefined,若在函数里面使用了这个赋值为undefined的形参,则可能会报错。如上述示例中,调用func2时只传入两个参数,而形参c就没有接受到传值,此时形参c将被赋值为undefined,若函数里面使用到了形参c,则可能会报错,如c.toString();就会报错。

上面提到,当实参的个数比形参的个数多时,多出来的实参将被隐式地存储在实参列表里,这个实参列表是一个隐式的数组,数组名为arguments,在函数里面可以通过访问arguments数组来使用多出来的实参。arguments数组存放的不仅限于多出来的实参,所有传入函数的实参都会被存放在arguments数组里。代码举例:

//将任意个数的参数求和
function sum(){
    var result = 0;
    for(var i = 0; i<arguments.length; i++){
        result += arguments[i];
    }
    console.log(result);
}
sum(1, 2, 3, 4, 5, 6, 7, 8, 9); //输出结果为45

实参列表与各参数相映射
修改实参列表arguments里的数值,会导致对应的参数的值发生改变,如

function fn(a){
    console.log(a);
    arguments[0] = 10;
    console.log(a);
}
fn(1);

执行结果为:

1
10

5 作用域

作用域是变量和函数生效的区域,分为全局和局部
在函数里面声明的变量是局部变量,该变量所在函数以外的区域将无法访问该变量
在函数外声明的变量是全局变量,在任何地方都可以访问到,如:

var a = 1;  //a在函数外声明,是全局变量
function func1(){
    var b = 2;  //b在函数内声明,是局部变量
    console.log(a, b);  //a和b都可以访问到
}
function func2(){
    console.log(a); //a是全局变量,可以访问a
    console.log(b); //b是func1的局部变量,不能在func2里访问b
}
console.log(b); //b是func1的局部变量,不能在func1函数外访问b

有种特殊的情况,在函数内部没有声明(没有使用var关键字)的变量也是全局变量:

function func(){
    a = 1;  //变量a未声明就赋值,属于全局变量
}
console.log(a); //在函数外部也可以访问到a

JavaScript 变量生命周期:
JavaScript 变量生命周期在它声明时初始化。
局部变量在函数执行完毕后销毁。
全局变量在页面关闭后销毁。

6 递归

什么是递归?
递归就是某一函数在其内部调用其本身的一种编程方式,通俗地讲就是"我自己调用我自己"

递归有什么作用?
在数学中,求某一数n的阶乘的方法是:
n的阶乘,等于n乘以(n-1)的阶乘,要求出其结果,又要先求出(n-1)的阶乘;
(n-1)的阶乘,等于(n-1)乘以(n-1-1)的阶乘,要求出其结果,又要先求出(n-1-1)的阶乘;
(n-1-1)的阶乘,等于(n-1-1)乘以(n-1-1-1)的阶乘,要求出其结果,又要先求出(n-1-1-1)的阶乘
...
禁止套娃!!!
像求n的阶乘这种问题,就可以使用递归来编程解决
其实递归就像是在玩俄罗斯套娃

在JavaScript中如何使用递归?
就用求n的阶乘来写代码举例:

function mul(n){
    if(n == 1){
        return 1;
    }
    return n * mul(n - 1);
}

递归编程技巧

  • 找规律,写返回
  • 找终值,写出口

递归的优缺点

  • 优点:代码简介,符合常人的思维逻辑
  • 缺点:空间复杂度高,执行速度慢

关于递归的优秀文章推荐

什么是递归?先了解什么是递归:https://www.cnblogs.com/Pushy/p/8455862.html
JavaScript中的递归:https://www.cnblogs.com/fundebug/p/9922876.html

posted @ 2020-04-22 22:52  xiaowus  阅读(168)  评论(0编辑  收藏  举报