JS基础<四>——函数,作用域

154 阅读1分钟

01-函数类型

1.0-函数介绍

  • 1.在实际开发中,我们有很多功能代码 并不是只执行一次,而是需要在很多个地方

    • 例如我们之前学习过的求和功能 :购物车页面需要求和,自己的订单列表页面需要求和查看总消费,还有待付款页面等等
    • 多个地方:可以是同一个程序员好多个页面都需要使用。 也可以是不同程序员所负责的页面
  • 2.那么既然是相同的功能代码,我们肯定不能复制粘贴去写冗余代码。这样万一功能有变化,维护起来就会很不方便

  • 3.而函数就是解决这些重复功能的 代码复用问题

    • 函数是一个数据类型,可以理解为存储代码的容器。 把这些代码给存到变量中,要使用的时候取出来执行即可。
    <script>
      需求:一段代码 需要在很多个地方使用 
​
      函数语法 
        
      1.声明函数 : 是一个存储过程,此时不会执行函数体代码  
            function 函数名(){
                函数体代码: 需要存储的一段代码
            }
​
      2.调用函数 : 执行函数体代码
            函数名()
​
      1.声明函数 : 把代码存入容器中
      function fn() {
        console.log("hello world")
​      }
      2.调用函数: 执行函数体代码
      调用者A
      fn()

    </script>

1.1-函数声明/调用

    <script>
       一段代码 需要在很多个地方使用 
​
      函数语法 
        
       1.声明函数 : 是一个存储过程,此时不会执行函数体代码  
            function 函数名(){
                函数体代码: 需要存储的一段代码
            }

       2.调用函数 : 执行函数体代码
            函数名()
​
      1.声明函数 : 把代码存入容器中
      function fn() {
        console.log("hello world")
      }
​
      2.调用函数: 执行函数体代码
      调用者A
      fn()
​
      调用者B
      fn()
    </script>
​

1.2-函数参数

    <script>
        0.函数语法: 函数是一种用于存储代码块的复杂数据类型
            * 作用:解决代码复用问题
        
        1.声明函数 : 声明函数只是把代码存起来,不会执行函数体  
            function 函数名(){
                函数体代码: 需要存储的一段代码
            }
​
        2.调用函数 : 执行函数体代码
            函数名()
​
        3.函数参数 : 调用者 传递数据 函数
            3.1 传:调用者
                函数名(实际参数)
            3.2 收:函数
                function 函数名(形式参数){   //函数体代码 }
            3.3 函数传参本质: 实参给形参赋值的过程
                (1)函数传参是按照传入顺序一一赋值
                (2)函数每一次调用传参过程都是独立的,互不影响
                (3)函数 形参数量 和 实参数量 可以不一致的
​
      声明函数
      function fn(x,y) {
        console.log(x,y) 
      }
​
      调用函数
      调用者A
      learn(10,20)
​
      调用者B
      learn(30,40)
    </script>

1.3-函数默认参数(逻辑短路运算)

    <script>
        1.函数默认参数,我们自己在开发中使用不多。(了解后面很多js框架函数默认参数底层原理)
        2.函数默认参数 使用 逻辑运算符短路运算(逻辑中断)
            2.1 短路运算: 左边式子就可以决定结果,右边式子不执行
                && : 一假则假
                || : 一真则真
                 ! : 取反(没有短路运算,因为只有一个式子)
            2.2 短路规则:
                && : 找假。  左边式子值可以转成false,则无条件返回左边式子的值,右边不执行。 反之无条件返回右边式子的值。
                || : 找真。 左边式子值可以转成true,则无条件返回左边式子的值,右边不执行。 反之无条件返回右边式子的值。 
​
        let res = undefined && 20
        console.log( res )//undefined
​
        let res1 = undefined || 20
        console.log( res1 )//20
        
      需求:给函数添加默认参数0
       (1)如果用户有传递实参,就使用用户传递的实参
       (2)如果没有传,就使用默认参数
      function getSum(num1,num2){
          num1 = num1 || 0
          num2 = num2 || 0
          console.log(num1+num2)
      }
      getSum(66) 
    </script>

1.4-函数返回值

    <script>
        0.函数语法: 函数是一种用于存储代码块的复杂数据类型
            * 作用:解决代码复用问题
        
        1.声明函数 : 声明函数只是把代码存起来,不会执行函数体  
            function 函数名(){
                函数体代码: 需要存储的一段代码
            }
​
        2.调用函数 : 执行函数体代码
            函数名()
​
        3.函数参数 : 调用者 传递数据 函数
            3.1 传:调用者
                函数名(实际参数)
            3.2 收:函数
                function 函数名(形式参数){   //函数体代码 }
            3.3 函数传参本质: 实参给形参赋值的过程
                (1)函数传参是按照传入顺序一一赋值
                (2)函数每一次调用传参过程都是独立的,互不影响
                (3)函数 形参数量 和 实参数量 可以不一致的
​
        4.函数返回值 : 函数 传递数据 给调用者
            4.1 传:函数
                function 函数名(){ return 值 }
            4.2 收: 调用者
                let 变量名 = 函数名()
            4.3 注意点
                (1)函数return关键字后面的代码不会执行的
                    * 只要有return关键字,函数体立即结束执行。
                (2)如果函数没有return,则默认返回值undefined
​ 
        写一个函数,求数组的和
        声明函数    
        function getSum(arr){
            let sum = 0
            for(let i =0;i<arr.length;i++){
                sum += arr[i]
            }
            返回值
            return sum
        }          
​
        调用者A
        let num1 = getSum([10,20,30,40,50])
        document.write(num1)
​
        调用者B
        let num2 = getSum([80,20,55,66])
        document.write(num2)
    </script>

03-作用域

1.1-作用域介绍

  • 注意:如果一个变量在声明的时候没有使用关键字。 例如: num = 10,此时这个变量无论写在哪里都是全局变量。 (切忌:这是非常不规范的,千万不要这么写,否则以后代码可能会出现bug)
    <script>
         1.js变量作用域: 变量可以使用的区域
            * 作用:避免变量污染(变量名相同导致代码冲突)
         2.js三种作用域
            2.1 全局作用域(全局变量)  : 在函数外面let的变量
            2.2 局部作用域(局部变量) :   在函数里面let的变量
            2.3 快级作用域(快级变量) :   在分支或循环大括号中let的变量  
​
        1.全局变量
        let num = 10
​
        function fn(){
            2.局部变量
            let age = 18
            console.log( num )
            console.log( age )
        }
        console.log(age)//报错。 局部变量只能在函数内部使用,函数外部无法使用
        fn()
​
        3.快级变量
        if(1){
            let sex = '男'
            console.log(sex)
        }
         console.log(sex)
​
        for(let i=1;i<=5;i++){
            console.log('循环内部:' + i )
        }
        console.log('循环外部:' + i) 
    </script>

1.2-作用域链

    <script> 
         1.js变量作用域: 变量可以使用的区域
            * 作用:避免变量污染(变量名相同导致代码冲突)
         2.js三种作用域
            2.1 全局作用域(全局变量)  : 在函数外面let的变量
            2.2 局部作用域(局部变量) :   在函数里面let的变量
            2.3 快级作用域(快级变量) :   在分支或循环大括号中let的变量
​
        3.作用域链: 默认情况下,代码处于全局作用域(0级链),当声明一个函数之后就会开辟一个局部作用域(1级),而函数里面又可以声明一个函数,又会形成新的作用域(2级),以此类推形成的结构称之为作用域链
        
        4.变量访问规则: 就近原则
            * 当你在一个作用域访问变量的之后,首先会看当前作用域有没有声明。如果有则访问。 没有则往上级作用域查找,有没有声明。有则访问,没有则继续往上。直到作用域最顶端0级,如果还没有找到。则程序报错  xxx is not defined
​
        0级
        let num = 10
        function fn1(){//fn1本身还是0级的,只是里面函数体是1级
            //1级
            let num = 20
            console.log(num)//20
​
            function fn2(){
                //2级
                let num = 30
                console.log(num)//30
            }    
            fn2()
        }
​
        fn1()
        console.log( num )//10
        
    </script>