六、函数

suaxi
2024-11-16 / 0 评论 / 48 阅读 / 正在检测是否收录...

1. 函数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>函数</title>
  </head>
  <body>
    <script>
        /*
        函数(Function):
            - 函数也是一个对象
            - 具有其他对象所有的功能
            - 语法:
                function 函数名() {
                    ......
                }
            - 调用函数:
                函数对象()
            - 使用typeof检查函数对象时返回的是function

        */

        function test() {
            console.log('这是一个函数')
            
        }

        //console.log(test)
        
        //调用函数
        test()

        console.log('typeof test()', typeof test)
        
    </script>
  </body>
</html>

2. 函数的创建方式

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>函数的创建方式</title>
  </head>
  <body>
    <script>
        /*
        函数的创建方式:
            - 函数声明:
                function 函数名() {
                    ......
                }
            - 函数表达式:
                const 变量 = function() {
                    ......
                }
            - 箭头函数:
                () => {
                    ...... 
                }
        */

        //方式一:方式一:函数声明
        function test() {
            console.log('方式一:函数声明')
            
        }
        test()

        //方式二:函数表达式
        const test1 = function() {
            console.log('方式二:函数表达式')
            
        }
        test1()

        //方式三:箭头函数
        const test2 = () => {
            console.log('方式三:箭头函数')
            
        }
        test2()
    </script>
  </body>
</html>

3. 参数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>参数</title>
  </head>
  <body>
    <script>
        /*
        形式参数:
            - 在定义函数时,可以在函数中指定数量不等的形式参数(形参)
            - 在函数中定义形参,等价于在函数内部声明了对应的变量,但没有赋值
        实际参数:
            - 在调用函数时,可以在函数的()中传递数量不等的参数(实际参数)
            - 实参会赋值给对应的形参
            - 注:
                如果实参多于形参,则多余的实参不会使用
                如果实参少于形参,则多于的形参值为undefined
        参数的类型:
            - 在js中不会检查参数的类型,可以传递任意类型的值作为参数
        
        1. 函数声明:
            function 函数名([参数]) {
                ......
            }
        2. 函数表达式:
            const 变量名 = function 函数名([参数]) {
                ......
            }
        3. 箭头函数:
            ([参数]) => {
                ......
            }
        */
       function sum(a, b) {
        console.log('两个数求和', a + b)
       }

       sum(1, 2)
    </script>
  </body>
</html>

4. 箭头函数的参数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>箭头函数的参数</title>
  </head>
  <body>
    <script>
      /*
      
      */

      const test = (a, b) => {
        console.log('参数a:', a)
        console.log('参数b:', b)
      }

      //当箭头函数只有一个参数时,可以省略括号
      const test1 = a => {
        console.log('这个箭头函数只有一个参数:', a)
      }

      //定义参数时,可以指定默认值
      const test2 = (a = 1, b = 2) => {
        console.log('a:', a)
        console.log('b:', b)
      }

      test2(30) //此时在控制台打印的值为 30,2
    </script>
  </body>
</html>

5. 对象作为参数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>对象作为参数</title>
  </head>
  <body>
    <script>
        function test(a) {

            a = {} //修改变量时,只会影响当前的变量

            a.name = '药水哥' //修改对象时,如果有其他变量指向该对象,则所有指向该对象的变量都会受到影响

            console.log('a', a)
        }

        let obj = {
            name: '孙笑川'
        }

        test(obj)

        console.log('obj', obj)
        
    </script>
  </body>
</html>

6. 函数作为参数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>函数作为参数</title>
  </head>
  <body>
    <script>
        /*
        在js中,函数也是一个对象
        */
       function test(a) {
        console.log('a', a)
       }

       function test1(a) {
        console.log('这是一个名叫test1()的函数')
       }

       test(test1)

       test(() => console.log('这是一个箭头函数'))
    </script>
  </body>
</html>

7. 函数的返回值

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>函数的返回值</title>
  </head>
  <body>
    <script>
        function test(a) {
            //在函数中,可以使用return关键字来指定函数的返回值
            return a
        }

        //let result = test('孙笑川')
        //console.log(result)
        
        console.log(test('孙笑川'))
        
    </script>
  </body>
</html>

8. 箭头函数的返回值

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>箭头函数的返回值</title>
  </head>
  <body>
    <script>
        //完整写法
        //const test = (a, b) => {
        //    return a + b
        //}

        //简写(函数体中只有一行代码的情况下)
        const test = (a, b) => a + b

        console.log(test(1, 2))
        
        //注:如果在箭头函数后设置对象字面量为返回值时,对象字面量必须用()括起来,不然js解释器解析不了它是一个对象还是一个函数
        const test1 = () => ({name: '孙笑川'})
        console.log('test1', test1())
        
    </script>
  </body>
</html>

9. 作用域

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>作用域</title>
  </head>
  <body>
    <script>
        /*
        作用域:
            - 指一个变量的可见区域
            - 全局作用域:
                - 在网页运行时创建,在网页关闭时销毁
                - 所有直接编写到script标签中的代码都位于全局作用域中
                - 可以在任意位置访问
            - 局部作用域:
                - 块作用域:
                    - 在代码块执行时创建,执行完毕后销毁
                    - 在块作用域中声明的变量是局部变量,只能在块内部访问
        */

        let name = '孙笑川'

        console.log('全局作用域 name', name)
        

        {
            let obj = {
                name: '药水哥'
            }

            let a = 1

            console.log('局部作用域-块作用域 obj', obj)

            {
                console.log('局部作用域-块作用域 a', a)
                
            }
        }

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

10. 函数作用域

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>函数作用域</title>
  </head>
  <body>
    <script>
        /*
        函数作用域:
            - 也是一种局部作用域
            - 在函数调用时创建,调用结束后销毁
            - 函数每调用一次都会产生一个新的作用域
            - 在函数中定义的变量是局部变量
        */

        function test() {
            let a = 1
        }

        //test()
        //test()
        test()
    </script>
  </body>
</html>

11. 作用域链

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>作用域链</title>
  </head>
  <body>
    <script>
        /*
        作用域链:
            - 当使用一个变量时,js解释器会优先在当前作用域中寻找变量
            - 如果找到则直接使用,如果没找到继续往上一层作用域寻找
            - 当全局作用域中也没找到时,报错xxx is not defined
            - 变量在函数中使用时同理
        */

        {
            let a = 1
            {
                let a = 2
                {
                    let a = 3
                    console.log(a)
                }
            }
        }
    </script>
  </body>
</html>

12. window对象

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>window对象</title>
  </head>
  <body>
    <script>
        /*
        window对象:
            - 浏览器为我们提供了一个window对象,可以直接访问
            - 它代表的是浏览器窗口,通过该对象可以对浏览器窗口进行各种操作
            - 它还负责存储js中的内置对象和浏览器的宿主对象
            - window对象中的属性可以通过window对象访问,也可以直接访问
            - 函数可以认为是window对象的方法
        */

        //alert('孙笑川')
        //window.alert('孙笑川')
        //window.console.log('孙笑川')

        window.a = 10

        console.log('a', a) //向window对象中添加的属性会自动成为全局变量
        
        /*
        var 用来声明变量,作用和let相同,但var不具备块作用域
            - 在全局中使用var声明的变量,都会作为window对象的属性保存
            - 使用function声明的函数,都会作为window的方法保存
        */

        var b = 20 //等价于window.b = 20

        function test() {
            console.log('孙笑川')
        }

        window.test()

        let c = 1
        console.log('let c', window.c) //undefined

        let d = 2
        window.d = 3
        console.log('d', d) //打印的值为2,let和window声明的变量相同时,会优先找let
        

        //不推荐此种写法
        {
            e = 5 //在局部/块作用域中,如果没有使用var/let声明变量,则变量会自动成为window的属性(全局变量)
        }
        console.log('e', e)
        
    </script>
  </body>
</html>

13. 变量、函数的提升

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>变量、函数的提升</title>
  </head>
  <body>
    <script>
        /*
        变量的提升:
          - 使用var声明的变量,会在所有代码执行前被声明
        */
        console.log('a', a)
        
        var a = 1

        a = 2

        /*
        函数的提升:
          - 使用函数声明创建的函数,会在其他代码执行前被创建
        */

        test()

        function test() {
          console.log('函数的提升')
        }

        /*
        let声明的变量也会提升,但是在赋值之前,js解释器会禁止访问该变量
        */
       console.log('c', c) //Uncaught ReferenceError: Cannot access 'c' before initialization
       
       let c = 3

       //注:提升的主要作用是js在设计时考虑到内存分配优化的问题
    </script>
  </body>
</html>

14. debug

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>debug</title>
  </head>
  <body>
    <script>
        /*
        debug:
            - debugger 在代码中打一个断点
            - f12控制台 - source模块下直接打
        */
    </script>
  </body>
</html>

15. 立即执行函数

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>立即执行函数</title>
  </head>
  <body>
    <script>
        //在开发时,应尽量避免在全局作用域中编写代码
        //方式一:如果使用let声明变量,可以使用{}来创建块作用域
        {
            let a = 1
        }

        {
            let a = 2
        }

        /*
        方式二:使用立即执行函数(不能使用let/需兼容旧浏览器等情时)

        立即执行函数(IIFE):
            - 它是一个匿名函数,且只会调用一次
            - 可以用它来创建一个一次性的函数作用域,避免变量冲突的题
        */
       (function() {
        let a = 1
        console.log('a', a)
       }())

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

16. this

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>this</title>
  </head>
  <body>
    <script>
        /*
        this:
            - 函数在执行时,js解释器每次都会传递进一个隐含的参数(this)
            - this会指向一个对象
                - this所指向的对象根据函数调用方式的不同而不同:
                  1. 以函数的形式调用,this指向的是window
                  2. 以方法的形式调用,this指向的是调用方法的对象
            - 通过this可以在方法中引用调用方法的对象
        */

        function test() {
            console.log('this', this)
            
        }
        test()

        const obj = {
            name: '孙笑川'
        }
        obj.test = test
        obj.test()

        const obj1 = {
            name: '药水哥',
            test
        }
        obj1.test()

        const obj2 = {
            name: '刘波',
            printName: function() {
                console.log('我的名字是', this.name)
            }
        }
        obj2.printName()
    </script>
  </body>
</html>

17. 箭头函数中的this

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>箭头函数中的this</title>
  </head>
  <body>
    <script>
        /*
        箭头函数:
            - 语法
                ([参数]) => {}
            
            - 无参箭头函数:
                () => {}

            - 一个参数:
                [参数] => {}

            - 多个参数:
                ([参数一], [参数二], ...) => {}

            - 函数体只有一行代码的函数:
                () => ...

            - 只返回一个对象的函数:
                () => ({...})

            - 有多行语句的函数:
                () => {
                    ......
                    return 返回值
                }
        
        箭头函数没有自己的this,它的this由外层作用域决定:
            - 箭头函数的this和它的调用方式无关,固定为window
        */

        function test() {
            console.log('test', this);
            
        }

        const test1 = () => {
            console.log('test21', this);
        }

        test() //打印结果 window
        test1() //打印结果 window

        const obj = {
            name: '孙笑川',
            test,
            test1,
            printName() {
                console.log('我的名字是', this.name)

                function innerTest() {
                    console.log('innerTest', this)
                }

                innerTest() //以函数形式调用,此处的this为window
            
                const innerTest1 = () => {
                    console.log('innerTest1', this)
                }

                innerTest1() //obj
            }
        }

        obj.test() //打印结果 obj
        obj.test1() //打印结果 window
        obj.printName()
    </script>
  </body>
</html>

18. 严格模式

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>严格模式</title>
  </head>
  <body>
    <script>
        /*
        js允许代码有两种模式:
            - 正常模式
                - 默认情况下,代码都运行在正常模式下
                - 能不报错的地方尽量不报错
                - 运行效率相对较低 
            - 严格模式
                - 禁止了一些正常模式下的语法
                - 更容易报错
                - 性能提升
            - 一般情况下建议使用严格模式(可以避免潜一些在的问题;提升性能)
        */

        //开启严格模式
        "use strict" //全局严格模式
        // a = 10 //Uncaught ReferenceError: a is not defined

        function test() {
            "use strict" //局部严格模式
        }
    </script>
  </body>
</html>
0

评论 (0)

取消