• 19-函数


    08-函数

    函数:就是将一些功能或语句进行封装,在需要的时候,通过调用的形式,执行这些语句。

    • 函数也是一个对象

    • 使用typeof检查一个函数对象时,会返回function

    一、声明函数

    1.声明函数
      <script>
        // 1.申明
        function foo() {
          //to do something
        }
    
        // 2.调用
        foo();
      </script>
    
    2.函数表达式创建函数
        // 1.申明
        var fn = function () {
          // to do something
        }
    
        // 2.调用
        fn();
    
    声明函数和函数表达式的区别
    • 声明函数在哪里都能调用
    • 函数表达式只有在表达式后面才能调用
      <script>
        function foo() {
          console.log('小艾');
          // 此时调用成功,原因是foo执行的时候将foo2压栈,这个时候foo2已然是个函数了
          ②foo2();
        }
    
    
        // 表达式声明的时候,只能在声明函数的后面调用 
        // ①foo2();
        var foo2 = function () {
          console.log('同学');//foo2 is not a function
        }
    
        // 申明变量调用时,在script标签中的任何位置调用都可以
        foo();
      </script>
    

    原理分析:

    //上面代码预解析
    function foo(){}
    var foo2 = undefined
    foo2 = function(){}
    foo()
    
    当在①的情况下,函数寒没有赋值给foo2,此时foo2还是undefined,所以调用foo2的时候会报错。
    当在②的情况下,函数foo()调用时,foo2已经赋值完毕,可以正常调用
    
    3.函数对象构造函数

    太没有可读性了!不建议使用

        //3.申明
        var fn2 = new Function('形参1', '形参2', '函数体')
        // 调用
        fn2(实参);
    

    二、调用函数

    函数名()
    
    自执行函数

    将函数转为表达式,再在后面跟一个括号,就可以自己调用自己了~

        // 转为表达式:(), +, ~, -
        (function foo() {
          console.log('小艾同学');
        })();
    
        ~ function foo2() {
          console.log('小艾同学1');
        }();
    
        +function foo3() {
          console.log('小艾同学2');
        }();
    

    三、函数的形参和实参

    1.形参

    形式上的参数。定义函数时传递的参数,当时并不知道是什么值,只是用来占位。
    形参本质上是一个局部变量。

    2.实参

    实际上的参数。调用函数时传递的参数,实参将会传递给函数中对应的形参。

    3.形参实参不匹配
      <script>
        function foo(a, b) {
          console.log(arguments);//函数自带的属性,函数调用时传入的所有的实参的集合,是一个伪数组
          return a + b;
    
        }
        var a = foo();
        console.log(a);//NaN不传实参
    
        var b = foo(1);
        console.log(b);//实参少于形参,会多出来的的形参默认值是undefined,进行运算返回的是NaN
    
        var c = foo(1, 2, 3, 4, 5, 6)
        console.log(c);//实参多余形参,只取跟形参对等个数的实参参与逻辑,多出来的不会丢失,所有的实参都会存入arguments
      </script>
    

    四、函数的返回值

    当函数运行的结果需要在其他地方使用时,就要返回值。

    • 在函数中,return后的语句都不会执行(函数在执行完 return 语句之后停止并立即退出函数)
    • 如果return语句后不跟任何值,就相当于返回一个undefined
    • 如果函数中不写return,则也会返回undefined
    • 返回值可以是任意的数据类型,可以是对象,也可以是函数。
    • return 只能返回一个值。如果用逗号隔开多个值,则以最后一个为准。
      <script>
        
        function fn() {
          console.log('小艾');
          return;//返回值后面没有内容也是返回undefined
        }
    
        // 没有return,默认返回undefined
        console.log(fn());//undefined
    
    
        function foo() {
          console.log('小艾');
          return 666;
          console.log('同学');//return后面的代码不会执行
        }
        console.log(foo());
    
        function getMax() {
          // return只能返回一个值,如果用,连接多个,只会返回最后面那个值
          // return Math.max(...arguments), Math.min(...arguments); //返回5
          // 如果要返回福讴歌,可以返回一个数组
          return [Math.max(...arguments), Math.min(...arguments)];//返回[999,5]
        }
        var res = getMax(5, 6, 8, 999);
        console.log(res);
      </script>
    

    五、arguments

    arguments是js的一个内置函数,只要函数调用,就会自动生成一个arguments
    不确定有多少个参数传递的时候,可以用 arguments 来获取

    • 是一个伪数组:有length属性,可以遍历,但是无法使用push()等数组方法

    六、函数作用域

    作用域是一个变量或函数的作用范围。作用域在函数定义时,就已经确定了。

    全局作用域与局部作用域
    • 全局作用域:作用于整个 script 标签内部,或者作用域一个独立的 JS 文件
    • 局部作用域:作用于函数内的代码环境
    作用域的上下级关系

    当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(就近原则)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错。

        var i = 1//最后来全局找
        function a(){
          var i = 2
          //再来它最近的父级找
          function b(){
            i++//先在内部找
            console.log(i)//3
          }
          b()
        }
        a()
        
    
    全局变量与局部变量
    • 全局变量:在全局作用域下面 声明 的变量,在script标签内所有的地方都可以访问和修改
    • 局部变量:在函数内部 声明 的变量,收到函数作用域的保护,只能在当前作用域访问
      • 两者生命周期
      • 全局变量:只有浏览器关闭时才会被销毁,比较占内存。
      • 局部变量:当其所在的代码块运行结束后,就会被销毁,比较节约内存空间。

    函数的形参是局部变量

      <script>
        function foo(a) {
          return a + 6;
        }
        var res = foo(1);
    
        console.log(res);//7
        // 函数的形参是一个局部变量,全局中无法访问
        console.log(a);// a is not defined
      </script>
    

    js中没有块级作用域

      <script>
        // js中没有块级作用域
        if (true) {
          var num = 123;
          console.log(num); //123
        }
    
        console.log(num); //123(可以正常打印)
    
        // 全局变量和局部变量仅存在函数中
        function fn() {
          var num1 = 123;
          console.log(num1);
        }
    
        console.log(num1);//num1 is not defined
      </script>
    

    js函数调用栈

      <script>
        function a(){
          console.log('a')
        }
        function b(){
          console.log('b')
          // 函数内部的代码还是按顺序执行的,遇到新的函数执行才会进行压栈操作
          a()
          console.log('b1')
        }
        function c(){
          console.log('c')
          b()
          console.log('c1')
        }
        // 在函数执行的时候会将该函数压入到执行栈里面,当函数代码执行的时候又遇到了函数执行语句,那么当前函数执行
        // 上下文暂停,将新函数压入栈中...当函数执行完毕以后会发生出栈操作,函数的执行上下文交回给紧挨着    
    		// 它的底下的函数
        c() // c b a b1 c1
    

    js中没有动态作用域,是词法作用域

      <script>
        // js的作用域是词法作用域/静态作用域,而不是动态作用域!!!!
        // 函数作用域的形成是在函数声明的时候就决定好了的,而不是在调用的时候
        var i = 0
        function a(){
          console.log(i)
        }
    
        function b(){
          var i = 1
          a() // 0
        }
        b()
      </script>
    
  • 相关阅读:
    爱信诺面试总结
    项目进展日志6
    项目进展日志5
    项目进展日志4
    项目进展日志3
    项目进展日志2
    项目阶段总结
    项目进展日志
    事物的ACID特性
    5.27作业
  • 原文地址:https://www.cnblogs.com/xiaoaitongxue/p/12748282.html
Copyright © 2020-2023  润新知