函数的概念

函数是程序中完成特定功能的代码片段.在使用函数的好处:

  • 可复用性高
  • 可维护性好

程序中的函数,从现实世界的角度来看就是各种行为. 例如:

  • 吃饭的行为,它就包括吃什么,怎么吃的的各种要素.
  • 去银行取钱,它就包含,去哪个银行,带上什么东西,取多少钱的各种要素
  • 玩游戏,玩什么游戏,怎么玩?例如玩劲舞团,需要按下那些键?

函数的分类

在我们写程序的过程中,经常要用到两种函数

  • 自定义函数,就是有程序员自己编写实现某种功能的函数
  • 系统函数,由系统提供的实现了某种功能的函数

自定义函数

代码格式:

function 函数名(形参列表){
    //需要实现的功能代码
    return 返回值
}
  • 函数名 函数名的声明和变量的声明的要求是几乎一样的.

    • 普通函数首字母要小写
    • 驼峰标识
    • 除了$和_之外,不能有其他特殊字符
    • 不能以数字开头
    • 见名知意
  • 形参列表,全称为“形式参数”是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传递的参数。 例如:

    • 银行给我们提供了取钱的方法,但是要求我们使用取钱方法的时候,提供账户,密码,还有要取的金额.那么银行要求提供的账户,密码,金额,在这个取钱方法里就是形参
  • 实参:调用函数时候,根据形参要求,在相同的顺序位置上放置相应的值.例如

    • 银行提供的取钱方法,它要求提供账号,密码和金额.它要求的这些内容都是形参.而当你把自己的账号,密码,和金额都告诉他.这些内容就是实际参数了.
    • 吃饭,当你要去吃饭的时候,你需要吃米饭,吃菜,喝汤.
  • 功能代码:就是要在函数里实现的具体功能和操作
  • 返回值: 当你期望做出某个行为之后,能够得到相应的回应.而回应的内容就是返回值.例如
    • 你使用银行提供的取钱的行数,你也提供相应的账号,密码和金额.银行校验也成功了.这时候,银行就应该将相应的数目的钱给你.而这个给你的这个钱就是返回值
    • 你去图书馆借书,提供了借书卡和书名.这时候你期望得到的那本书,就是一个返回值

自定义函数也分几种

  1. 无参数无返回值函数
    function test(){
     console.log("Hello 函数");
    }
    
  2. 有参数无返回值函数
    function sayGoodBye(name){
      console.log(name+"我去上学了!");
    }
    
  3. 有参数有返回值函数
    function borrowBook(cardID,bookName){
     //假设cardId没问题,true
     if(true){
         return "这是您的"+bookName+",请拿好!"
     }else{
         return "抱歉你的卡已经过期了"
     }
    }
    

函数调用

函数名()

课堂练习

  1. 定义一个函数,该函数返回1-100之间所有整数之和
  2. 定义一个函数,该函数实现,向浏览器页面输出一个杨辉三角
  3. 定义一个函数,求1到任意数之间的基数的和

匿名函数

所谓匿名函数就是没有名字的函数,代码格式如下:

function(){

}

但是在程序中,不能直接使用以上方式定义函数,会报错说缺少函数名.

匿名函数的使用方式

  • 赋值匿名函数
  • 立即执行匿名函数

立即执行函数

顾名思义就是声明之后马上执行,这类型的函数常常用于一些,只需要执行一次的行为.

(function(){
    console.log("立即执行函数");
})();

(function(){
    console.log("立即执行函数");
}());

+function(){
    console.log("立即执行函数");
}();
-function(){
    console.log("立即执行函数");
}();
~function(){
    console.log("立即执行函数");
}();
!function(){
    console.log("立即执行函数");
}();

为什么说,匿名函数的主要作用是运行那些只需要执行一次的代码,

通过定义一个匿名函数,创建了一个新的函数作用域,相当于创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏污染全局的命名空间。此时若是想访问全局对象,将全局对象以参数形式传进去即可,如jQuery代码结构:

(function(window,undefined){

})(window)

赋值匿名函数

将匿名函数作为值存储到一个变量中,然后通过 "变量名()"的方式对函数进行调用

var func = function(){
    console.log("匿名函数");
}
//函数调用
func();

普通函数和赋值匿名函数的区别

  • 当定义普通函数的时候,程序会在预编译的时候就对该函数进行编译,以达到在整个script任意地方都可以使用该函数
  • 赋值匿名函数,受限于程序赋值事件的问题.赋值匿名函数无法在赋值之前使用
    f1();
    function f1(){
      console.log("我可以在任意地方使用");
    }
    f1();
    // 赋值匿名函数
    f2();//报错说f2不是一个函数,程序断开
    var f2 = function(){
      console.log("我只能在赋值之后才能被调用");
    }
    f2();
    

作用域

每个变量在定义之后,都会有它的作用范围.这个范围就是作用域.按照范围来分,作用域分为两种.

  • 全局作用域 顾名思义就是该变量作用于整个script标签内.当我们在函数体通过var声明变量,那么该变量的作用域就是全局作用域.
  • 局部作用域 在函数体内声明的变量只能作用于函数体内.在函数体外无法使用该变量.

变量提升

无论是在函数体外声明的变量还是函数体内声明的变量,这些默认都会作用于它整个作用于.例如

  • 以下声明的变量,可以作用于真个script标签内.

    <script> 
      console.log(webSite); //undefined
      var webSite = "www.githuo.com";
      console.log(webSite); //www.githuo.com
    </script>
    

    以上例子,可以写成以下方式

    <script>
      //将变量的声明放在script标签的第一行
      var webSite;
      console.log(webSite); //undefined
      webSite = "www.githuo.com";
      console.log(webSite);
    </script>
    
  • 函数作用域例子

    function func(){
      console.log(webSite);//undefined
      var webSite = "www.githuo.com";
      console.log(webSite); //www.githuo.com
    }
    func();
    

课堂练习

var webSite = "www.taobao.com";
function func(){
    console.log(webSite);
    var webSite = "www.githuo.com";
    console.log(webSite);
}
func()

递归

在程序中函数直接或间接调用自己,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的程序就可描述出解题过程所需要的多次重复计算,大大地减少了程序的代码量。

  • 代码模式
function 函数名(){
    // 行为
    函数名();//在函数体内调用自身
}
  • 退出条件 如果只在函数体内调用自身,没有设置退出条件,则递归会一直运行下去,直到程序出错或者你关闭程序.因此我们在用递归的时候,需要设置递归的退出条件.

例如:

var i = 0;
function count(){
    i++;
    sum += i;
    count();
}
count();
console.log(sum);//该语句无法执行

设置退出条件

var i = 0;
var sum = 0;
function count(){
    i++;
    if(i<=4){
        sum+=i;
        count();
        console.log("i=",i);
    }else{
        return 0;
    }
}
count();
console.log(sum);//该语句无法执行

该例子计算0到4之间所有整数的和,当i等于4的时候,进行最后一次运算和最后一次调用count自身,当i=5的时候,就不再满足继续调用自身的条件,通过return结束递归.

如图:

使用递归,画出杨辉三角

var i = 0;
function sanjiao(num){
    if(i<=num){
        console.log(i);
        for(var j=0;j<=i;j++){
            document.write("*")
        }
        document.write("<br/>");
        i++;
        sanjiao()
    }else{
        return;
    }
}
sanjiao(4);

课堂练习:

  • 使用递归计算10的阶乘

    function jc(n){
      // 1!=1,根据1!=1*0!,所以0!=1而不是0。
      if(n==0){
          return 1
      }
      //n乘以n-1的阶乘
      return n*jc(n-1);
    }
    console.log(jc(5));
    
    • 有个人想知道,一年之内一对兔子能繁殖多少对?于是就筑了一道围墙把一对兔子关在里面。已知一对兔子每个月可以生一对小兔子,而一对兔子从出生后第3个月起每月生一对小兔子。假如一年内没有发生死亡现象,那么,一对兔子一年内(12个月)能繁殖成多少对?(兔子的规律为数列,1,1,2,3,5,8,13,21)
    function fbn(n){
      if(n==1 || n==2){
          return 1;
      }
      return fbn(n-1)+fbn(n-2)
    }
    fbn(10)
    

课堂练习

  1. 用js实现函数f,f返回每次调用参数列表和之积.集中函数f可以不限次数调用.每次调用的参数个数不定, 此处假定传入的都是合法数字,且计算结果不会溢出 例如: f(1,2)(3)(4,5,6)实现功能 (1+2)x3x(4+5+6) 返回结果为135 f(1)(2,3)的返回结果为5

results matching ""

    No results matching ""