第五章 函数

98 阅读5分钟

一. 函数

1. 函数概念

  • 定义:函数是具有某种特定功能的代码块
  • 本质:函数其实本质也是一种数据,属于对象数据类型。
  • 作用:
    • 解决代码的冗余问题,形成代码复用
    • 可以把整个代码项目通过函数模块化
    • 封装代码,让函数内部代码对外不可见

2. 函数组成

  • 组成:
    • 函数名:命名规则同变量名一致
    • 函数体:函数的内容,代码块
    • 参数:形参和实参
    • 返回值:函数调用表达式的结果
  • 声明代码:
声明   function 函数名(形参1,形参2……){函数体 return返回值}
调用   函数名()

3. 定义函数的三种方式

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

}
function 函数名(参数) {

}
  • 表达式方式
var 函数名 = function(){

}
var 函数名 = function(参数) {

}
  • function构造函数方式
var 函数名 = new Function('函数体');
var 函数名 = new Function('参数', '函数体')

4. 函数调用

  • 函数调用表达式:函数名() 表达式的值就是函数的返回值
  • 函数名本质上是变量,后边不加()不会调用,函数内的代码也不会执行

5. 函数的返回值

  1. 返回值
  • return:函数体内的return右边的表达式(变量/直接量)便是函数的返回值
  • 函数名()的值就是函数的返回值
  • 函数体内没有写return或者return右边是空的,默认值会返回undefined
  • return除了设置返回值外,还可以结束函数的执行,return之后的代码不会执行
  • break:这个可以打破循环直接返回
  • continue:返回循环本身继续循环
let btn = document.getElementById('btn')
let h1 = document.getElementById('h1')
//给btn的onclick事件绑定一个函数
btn.onclick = function(){
    if(flag){
        h1.style.display = 'none';
        flag = false;
        return //条件一旦成立,那么return下边的代码就不再执行
    }
    h1.style.display = 'block';
    flag = ture;
}
  1. 那些函数需要返回值
  • 用作计算,最后的计算结果需要使用时需要写返回值
  • 函数的功能是实现某个具体的操作(界面操作),无需返回值

6. 函数的参数

  1. 形参和实参
  • 形参:声明函数的时候,给的参数,类似于变量名
  • 实参:调用函数时给的值,类似于赋值
  1. 形参和实参数量问题
  • 正常情况下,实参数量等于形参数量
  • 如果实参数量大于形参数量,多出来的实参,将被省略,如若想导出全部实参可借鉴arguments说明
  • 如果实参数量小于形参数量,有的形参没有确定的实参,取默认值undefined 。
  1. 形参的默认值
  • js函数允许形参有默认值,有默认值的形参,再调用函数时,可以没有与之对应的实参
  • 默认值的设置(es6):function(b,a=0){}
  • 默认值设置(es5):function(a,b){ a=a||0;b=b||0 }
function add(a,b){
    //需要给ab设置默认值0
    //提升代码健壮性(容错率)
    //es5这样写
    a = a||0;
    b = b||0;
    return a + b
}
function f1(a=1){
//这种赋予默认值的条件就是 只要a对应的实参不是null 赋予默认值都不起作用
console.log(a);

}

/* 
创造函数
function 函数名(形参){}

*/
  • 注意:有默认值的形参一定要放在后边!
  1. 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)

  1. 匿名函数
  • 定义:即没有名字的函数
  • 注意:匿名函数声明完要立即调用,否则没有意义
function() {
    //匿名函数
}
  1. 自调用函数
  • 函数声明完立即调用,称之为自调用函数,也叫立即调用函数,英文简称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(){}();
  1. 注意
  • 两个连续的自调用函数之间必须加分号,告诉浏览器是不同的函数,否则会有语法错误。
  • 在后边的自调用函数前加 '!' 等没有副作用的一元运算符也可以起隔离作用

练习

//开关灯实例练习
//场景:仿照小说的夜间日间模式设置开关灯案件
<body>
    <button>开灯</button>
    <button>关灯</button>
    <h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
    <h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
    <h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
    <h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>
    <h1>sdgfsdgsgfsdgsdgfsdgsdgsd</h1>

    <script>
        let btn = document.getElementsByTagName('button');
        console.log(btn[0],btn[1]);
        let body = document.body;
        let h=document.getElementsByTagName('h1')
       
        btn[0].style.display = 'none'
        //ture时为开灯false为关灯
        
            btn[1].onclick = function () {
                btn[1].style.display = 'none'
                btn[0].style.display = 'block'
                body.style.background = 'black';
                body.style.color = "#FFF";
              

            }
        
            btn[0].onclick = function () {
                btn[0].style.display = 'none'
                btn[1].style.display = 'block'
                body.style.background = '#fff';
                body.style.color = 'black';
                

            }

        
    </script>
</body>

9. 箭头函数(es6新增)

  • 函数代码:var 函数名=(形参1,形参2……)=>{return 返回值};
  • 如果形参只有一个,那小括号可以省略
  • 如果函数体只有return一条语句,那大括号也可以省去
  • 箭头函数不能使用arguments
  • this也不能使用
//转换为箭头函数 
         function (a,b){
              ruturn a+b;
          } 
        // var  f=(a,b)=>{ return a+b;};


 //箭头函数转换为字面量式/表达式
         var result = index => index + 1;

        function result(index) {
            return index + 1;
        };
        var result = function(){
            return index + 1;
        }; 
         

10. caller和callee

  • caller:全局变量
  • callee:局部变量
 function outer(){
            //函数执行的宿主环境,如果是全局,那就是null
            console.log(outer.caller);
            inner();
        };
        function inner(){
            //函数身上有个caller inner在outer里面调用,宿主环境就是outer
            console.log(inner.caller);//outer函数
            console.log(arguments.callee);//函数本身
            console.log(arguments.callee.caller);//outer

        }

11. 选项卡

<!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;
            list-style: none;
        }

        .container {
            width: 1000px;
            margin: 0 auto;
        }

        .container>div {
            width: 600px;
            height: 300px;

            text-align: center;
            line-height: 300px;
            display: none;
        }

        .container>.current {
            background: red;
            display: block;

        }

        ul>.current {
            background: green;
        }

        ul {
            font-size: 0;
        }

        ul>li {
            display: inline-block;
            width: 100px;
            height: 80px;
            line-height: 80px;
            text-align: center;
            font-size: 22px;
        }
    </style>
</head>

<body>
    <div class="container">
        <ul>
            <li class="current">吃饭</li>
            <li>睡觉</li>
            <li>打豆豆</li>
        </ul>
        <div class="current">不吃饭</div>
        <div>不睡觉</div>
        <div>不打豆豆</div>
    </div>
    <script>
        let list = document.querySelectorAll('li');
        let box = document.querySelectorAll('.container div');
        for (var i = 0; i < list.length; i++) {
            list[i].record = i;
            list[i].onclick = function () {
                for (var a = 0; a < list.length; a++) {
                    list[a].className = '';
                    box[a].className = '';

                }
                 this.className = 'current';
                 box[this.record].className = 'current';
            }
        }
    </script>
</body>

</html>

12. 补充

  • this:指事件绑定的元素
  • debugger:断点
  • argument,this都是函数中特殊的存在