09.函数(function)

函数(Function)

  • 函数也是一个对象(JS中万物皆对象)
  • 它具有其他对象所有功能
  • 函数中可以存储代码,且可以在需要的时候调用这些代码

语法:

function 函数名( ){

  语句...

}

调用函数:

  • 调用函数就是执行函数中所存储的代码
  • 语法:函数对象( )
  • 使用typeof检查函数对象时会返回function

代码

查看代码

 <script>
        // 创建一个函数
        function fn() {
            console.log("你好!")
            console.log("hello!")
            console.log("萨瓦迪卡")
        }
        // 调用函数
        fn()//你好!hello!萨瓦迪卡
        fn()//你好!hello!萨瓦迪卡
        fn()//你好!hello!萨瓦迪卡

        // 使用typeof检查函数对象
        console.log(typeof fn) //function
</script>

函数的定义方式

函数声明

function 函数名( ){

  语句...

}

函数表达式

const 变量 = function ( ){

  语句...

}

箭头函数

const 变量 = ( )=>{

  语句...

}

const 变量 = ( )=> 语句...

查看代码

<script>
        function fn1() {
            console.log("函数声明")
        }
        const fn2 = function () {
            console.log("函数表达式")
        }
        const fn3 = () => {
            console.log("箭头函数1")
        }
        const fn4 = () => console.log("箭头函数2")
        fn1() //函数声明
        console.log(typeof fn1) //function
        fn2() //函数表达式
        console.log(typeof fn2) //function
        fn3() //箭头函数1
        console.log(typeof fn3) //function
        fn4() //箭头函数2
        console.log(typeof fn4) //function
</script>

参数

形式参数

  • 在定义函数时,可以在函数中指定数量不等的形式参数(形参)
  • 在函数中定义形参,相当于在函数内部声明了对应的变量但没有赋值

实际参数

  • 在调用函数时,我们可以在函数的( )中传递数量不等的实参
  • 实参会赋值给对应的形参
  • 参数:
    • 如果实参和形参数量相同,则对应的实参会赋值给对应的形参
    • 如果实参多于形参,则多余的实参不会使用(下面两种情况在别的语言中肯定报错,但JS不会,应为JS曾经是以不报错为最高原则的语言)
    • 如果形参多于实参,则多于的形参显示undefined

参数类型

  • JS中不会检查参数的类型,可以传递任何类型的值作为参数
  • 对象也可以作为参数传递,并且在函数中修改对象,其“真实”对象也会改变。
  • 函数作为参数,函数也是一个对象(一等函数),别的对象能做的事函数也可以。

参数默认值

  • 定义参数时,可以为参数指定默认值
  • 默认值,在没有对应的实参时生效
  • 当默认值是{ }时,每次调用此函数,默认值对象都是一个新对象。

参数:

<script>
        /* 定义两个可以求和的函数 */
        function sum1(a, b, c) {
            console.log(a + b) //3
        }
        const sum3 = (a, b) => {
            console.log(a + b) //helloworld!
        }
        sum1(1, 2, 3)
        sum3("hello ", "world!")
    </script>

参数默认值:

<script>
        // 添加默认值
        const fn = (a = 10, b = 20, c = 30) => {
            console.log("a = ", a) //a = 1
            console.log("b = ", b) //b = 2
            console.log("c = ", c) //c = 30
        }
        // 传两个实参
        fn(1, 2)
    </script>

 函数作为参数:

<script>
        function fn(a) {
            a()
        }
        // 调用1
        fn(
            () => console.log("我是传进来的箭头函数!")
        )
        // 调用2
        fn(
            function () {
                console.log("我是传进来的匿名函数")
            })
    </script>

思考一:

当我第一次调用fn时,将a指向的对象name改为了"猪八戒",那我们第二次调用fn时是一个孙悟空一个猪八戒还是两个都是猪八戒呢?

<script>
        // 函数每次调用都会重新创建默认值
        function fn(a = { name: "孙悟空" }) {
            console.log("a = ", a.name)
            a.name = "猪八戒"
            console.log("a = ", a.name)
        }
        fn()
        fn()
    </script>

当默认值是{ }时,每次调用此函数,默认值对象都是一个新对象。

但是下面这种情况例外:

        // 对象
        const obj = { name: "孙悟空" }
        // 函数
        function fn(a = obj) {
            console.log("a = ", a.name)
            a.name = "猪八戒"
            console.log("a = ", a.name)
        }
        fn()
        fn()

 应为对象定义在外面,所以a指向的对象发生改变,后面的所有指向他的变量也都改变。

函数的返回值

  • 在函数中可以通过return关键字来指定函数的返回值
    • 返回值就是函数的执行结果,函数执行完毕返回值便会作为结果返回
  • JS中任何值都可以作为返回值使用(包括对象和函数之类)
    • 如果return后不跟任何值,则相当于返回undefined
    • 如果不写return,函数的返回值依然是undefined
  • return一执行函数立即结束,后面的代码不再执行
<script>
    function sum(a, b) {
        return a + b; //返回值 5
    }

    console.log(sum(1, 4))
</script>

 特殊

  • 箭头函数的返回值可以直接写在箭头后(前提只有返回值这一句话)
  • 如果直接在箭头后设置对象字面量的返回值时,对象字面量必须用()括起来(不然会被当成代码块处理)

 

返回值

const sum1 = (a, b) => a + b;
console.log(sum1(2, 3)) // 5

 返回对象

<script>
        const fn1 = () => { name: "孙悟空" }
        console.log(fn1()) //undefined

        const fn2 = () => ({ name: "孙悟空" })
        console.log(fn2()) //Object { name: "孙悟空" }
</script>

作用域(scope)

  • 作用域指的是一个变量的可见区域
  • 作用域分为两种:
    • 全局作用域
      • 在网页运行时创建,在网页关闭时销毁
      • 所有直接编写到script标签中的代码都位于全局作用域中
      • 全局作用域中的变量是全局变量,可以在任意位置访问
    • 局部作用域
      • 块作用域
        • 块作用域是一种局部作用域
        • 块作用域在代码块执行时创建,在代码块执行完毕时销毁
        • 在块作用域中声明的变量是局部变量,只能在块中访问,外部无法访问
      • 函数作用域
        • 函数作用域在函数调用时创建,调用结束后销毁
        • 函数每次调用都会产生一个全新的函数作用域
        • 在函数中定义的变量是局部变量,只能在函数内部访问,外部无法访问

作用域链

当我们使用一个变量时,JS解释器会就近原则先在当前作用域中找变量

  • 如果找到则直接使用
  • 如果没找到则去上一层作用域中找,找到了则使用
  • 如果没找到则继续上一层找,以此类推
  • 如果到全局作用域都没找到,则报错 xxx is not defined
<script>
        // 全局变量
        let a = 10
        // 局部块
        {
            let a ="第一代码块中的a"
            {
              let a = "第二代码块中的a"  
              console.log(a); //第二代码块中的a
            }
        }
    </script>

 

posted @ 2022-11-08 20:06  莫扎特03  阅读(362)  评论(0)    收藏  举报