1. 函数的概念

1.1 什么是函数

函数具有某种特定功能的代码块。
函数其实本质也是一种数据,属于对象数据类型

1.2 为什么要有函数

1)解决代码的冗余问题,形成代码复用。
2)可以把整个代码项目,通过函数模块化。
3) 封装代码,让函数内部的代码对外部不可见。

2. 函数的组成

函数的声明:
JS-第一周day05 - 图1
函数的调用:
image.png
函数由如下部分组成:

  • 函数名,命名规则同变量名一致。
  • 函数体, 函数的内容,代码块。
  • 参数, 分为形参实参
  • 返回值, 函数调用表达式的结果

    3 定义函数的三种方式

  • function关键字方式/字面量方式 ```javascript function 函数名() {

} function 函数名(参数) {

}

  1. - 表达式方式
  2. ```javascript
  3. var 函数名 = function(){
  4. }
  5. var 函数名 = function(参数) {
  6. }
  • Function构造函数方式
    var 函数名 = new Function('函数体');
    var 函数名 = new Function('参数', '函数体')
    

    4 函数调用

    1) 在函数名后面加上 () 就是对函数的调用,函数内的代码会执行。
    2) 函数名后面不加() 不会调用函数,函数内的代码也不会执行;函数名本质上是个变量名,通过函数名可以引用到函数本身。

    5 函数的返回值

    5.1 返回值

    1)函数名() 被称之为函数调用表达式, 表表达式的值就是函数的返回值
    2)在函数体内,return 右边的表达式(或变量、直接量)便是函数的返回值。
    3)函数体内没写 return 或者 return 的右边是空的,默认默认会返回 undefined。
    4)return 除了设置返回值外,还可以结束函数的执行,return 之后的代码不会执行。

    5.2 那些函数需要些返回值

    什么样的函数需要写返回值?
    如果函数的作用是进行某种计算,得到的计算结果最后以返回值的形式返回。
    什么样的函数不需要返回值?
    函数的功能是实现某个具体的操作(界面操作),无需返回值。

    6 函数的参数

    6.1 形参和实参

    形参: 声明函数的时候,给的参数, 类似于变量名;在声明函数的时候,参数是没有值。
    实参:调用函数是给的参数; 实参会按照顺序赋值给形参。

    6.2 形参和实参的数量问题

    正常情况下,实参数量应该等于形参数量。
    如果实参数量大于形参数量, 多出来的实参,将被忽略。
    如果实参数量小于形参数量, 有的形参没有对应的实参,取默认值 undefined。

    6.3 形参的默认值

    JS函数允许形参有默认值,有默认值的形参,在调用函数的时候,可以没有与之对应的实参!
    如何实现形参的默认值?
    function demo(a, b=默认值) { } 
    注意: 有默认值的形参一定要放在后面!
    
    es6才可以这么写,那问题来了,如果es6前应该怎么去设置默认值
    image.png

    6.4 arguments

    arguments 只能在函数内使用。

arguments 是一个类数组对象,具有数组的一些特性。

arguments可以获取所有的实参,所以我们想获取实参的话有两种方式:①用形参;②使用arguments。

用途:如计算所有参数和,取参数中的最大值,取参数中的最小值,求所有参数平均数。

/**
 * 取所有参数里面的最大值
 */
function max() {
  //设置遍历 默认值的最大值
  var res = arguments[0];
  // 循环比较
  for (var i = 0; i < arguments.length; i ++) {
    if (arguments[i] > res) {
      res = arguments[i];
    }
  }
  // 返回结果
  return res;
}

/**
 * 取所有参数里面的最小值
 */
function min() {
  var res = arguments[0];
  // 循环比较
  for (var i = 0; i < arguments.length; i ++) {
    if (arguments[i] < res) {
      res = arguments[i];
    }
  }
  // 返回结果
  return res;
}
/**
 * 取所有参数的和
 */
function total() {
  var res = 0;
  for (var i = 0; i < arguments.length; i++) {
    res += arguments[i];
  }
  return res
}
console.log(total(1, 2, 3, 4, 5))


/**
 * 取所有参数的平均数
 */
function average() {
  var res = 0, ave = 0;
  for (var i = 0; i < arguments.length; i++) {
    res += arguments[i];
  }
  ave = res / arguments.length;
  return ave
}
console.log(average(1, 1, 4));

7 函数的嵌套

函数体内是可以再嵌套函数的。

8 自调用函数 IIFE(Immediately Invoked Function Expression)

8.1 匿名函数

没有名字的函数称之为 匿名函数

function() {
    //匿名函数
}

匿名函数声明完之后要立即调用,否则没有意义。

8.2 自调用函数

函数声明完立即调用,称之为自调用函数,也叫立即调用函数,英文简称 IIFE,英文全称 Immediately Invoked Function Expression

// 函数允许匿名,但是匿名的函数要立即使用
// 自调用函数,立即调用函数
(function(){
console.log('哈哈哈,我被调用了');
})();

// 自调用函数 传参
(function(a, b){
console.log(a+'和'+b+'跳舞');
})('曹操', '刘姥姥');


// 当然不匿名的自调用函数也是可以的,不过没有意义
(function fn(){
  console.log('fn 被调用了');
})();


 (function(){})();

  ~function(){}();

  +function(){}();

  -function(){}();

  !function(){}();

注意:
两个连续的自调用函数,之间必须加分号,告诉浏览器是不同的函数,否则会有语法错误。
或者,在后面的自调用函数前加 ! 等没有副作用的一元运算符。

练习

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>函数的练习</title>
</head>
<body>
<button id="red">红色</button>
<button id="green">绿色</button>
<button id="blue">蓝色</button>
<button id="pink">粉色</button>

<script>
    /*
    * 当点击不同的按钮的时候 让页面加载相应的颜色
    * 改变屏幕的颜色 就是控制body的背景颜色
     */
    var oBody=document.getElementsByTagName("body")[0];
    var oRed = document.getElementById("red");
    var oGreen = document.getElementById("green");
    var oBlue = document.getElementById("blue");
    var oPink = document.getElementById("pink");

    function changeColor(col){
        oBody.style.backgroundColor = col;
    }
    oRed.onclick=function () {
        changeColor("red");
    }
    oGreen.onclick=function () {
        changeColor("green");
    }
    oBlue.onclick=function () {
        changeColor("blue");
    }
    oPink.onclick=function () {
        changeColor("pink");
    }

</script>
</body>
</html>

9 箭头函数

箭头函数不能使用arguments

var fn=function(a,b){
    return a+b
}


var fn=(a,b)=>{
    return a+b;
}

// 如果执行语句只有一条,return 也可以省去
var fn=(a,b)=> a+b;


// 如果参数只有一个,小括号也可以省去

var fn=a=>a+2;
fn(3)

caller 和 callee

function outer() {
  console.log(outer.caller)//当前这个函数的宿主环境是全局,所以是null
  inner()
}
function inner() {
  //这里指的是当前这个函数的宿主函数
  console.log(inner.caller)//outer函数
}
outer()

image.png

10 选项卡

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    *{
        margin:0;
        padding:0;
    }
    ul,ol{
        list-style: none;
    }
    .main{
        width:500px;
        margin:0 auto;
    }
    ul>li{
        width:100px;
        height:40px;
        line-height: 40px;
        text-align:center;
        border:1px solid #333;
        margin-right:10px;
        display:inline-block;
        position:relative;
        top:1px;
    }
    .main>div{
        height:300px;
        line-height: 300px;
        border:1px solid #333;
        text-align:center;
        display:none;
    }
    .main li.current{
        background:darkcyan;
        border-bottom-color:darkcyan;

    }
    .main div.current{
        background:darkcyan;
        display:block;
    }
    </style>
</head>
<body>
    <div class="main" id="main">
        <ul>
            <li class="current">音乐</li>
            <li>电视</li>
            <li>综艺</li>
        </ul>
        <div class="current">音乐内容</div>
        <div>电视内容</div>
        <div>综艺内容</div>
    </div>
</body>
</html>
<script>
  var main=document.getElementById("main");
  var lis=main.getElementsByTagName("li");
  var divs=main.getElementsByTagName("div");

  for(var i=0;i<lis.length;i++){
       lis[i].index=i;
       lis[i].onclick=function(){
           for(var i=0;i<lis.length;i++){
                 lis[i].className="";
                 divs[i].className="";
           }
           var index=this.index;
           lis[index].className="current";
           divs[index].className="current";
       }
  }

</script>