JavaScript中的函数进阶

·  阅读 64

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

函数声明与表达式的联系与区别

联系

它们都是一个函数对象, 调用方式没有什么不同

区别

  1. 浏览器在执行js代码前, 会先扫描代码, 对于函数声明会进行处理, 而对于函数表达式不会优先处理
  2. 浏览器如何处理函数声明呢? 浏览器在扫描到函数声明时, 会创建这个函数, 然后将函数的引用赋值给一个变量, 而这个变量名就是该函数名
  3. 浏览器对于函数表达式的处理跟对其它变量的处理逻辑是一样的
  4. 在调用位置上是不同的, 你可以在任何位置调用一个函数声明的函数, 而只能在函数表达式的后面调用该函数
  5. 对于函数声明是隐式的将函数引用同事赋值给一个变量, 对于函数表达式是显式的将函数引用赋值给一个变量

提升

使用函数声明来定义的函数, 你可以在任何地方声明这个函数, 也可以在任何地方调用函数声明的函数, 这就是函数提升

函数声明

function 函数名() {

// 函数体

}

函数表达式

let 变量名 = function() {

// 函数体

}

        // 函数声明
        function test1() {
            console.log('test1');
        }

        // 函数表达式
        let test2 = function() {
            console.log('test2');
        }
复制代码

函数作为参数

        let arr = [            {name: 'shaosiming', age: 16},            {name: 'dasiming', age: 18},            {name: 'tianming', age: 9},            {name: 'yuer', age: 8},            {name: 'shaoyu', age: 10}        ];

        // 按年龄从小到大排序
        // arr.sort((a, b)=>{
        //     return a.age - b.age;
        // })

        // 按姓名排序
        arr.sort((a, b)=>{
            return (a.name > b.name ? 1 : (a.name === b.name ? 0 : -1));
        })
        console.log(arr);
复制代码

函数作为返回值

        function add(a, b) {
            return a + b;
        }
        function sub(a, b) {
            return a - b;
        }
        function getFunc(str) {
            if (str === '+') {
                return add;
            } else if (str === '-') {
                return sub;
            }
        }
        console.log(getFunc('+')(3, 5));
        console.log(getFunc('-')(3, 5));
复制代码

匿名函数

在js中匿名函数的使用频率是超级高的, 这不仅大大方便了我们的编码

在使用匿名函数的时候, 我们还可以使用一些空格和换行让代码更易读

例如我们在绑定onload事件的时候, 就可以将一个匿名函数赋值给onload这个事件

        // 第一种方式
        // function init() {
        //     console.log("load finished!");
        // }
        // window.onload = init;

        // 第二种方式
        window.onload = function() {
            console.log("load finished...!");
        }
复制代码

函数的嵌套

在函数内部使用嵌套函数的规则, 其实与使用全局函数的规则是一样的

在函数内部使用函数声明创建的嵌套函数, 则在该函数内部的任何地方都可调用这个嵌套函数

在函数内部使用函数表达式创建的嵌套函数, 则只能在嵌套函数表达式后才是可调用的

        function test3() {
            test33();
            console.log('test33声明前');
            function test33() {
                console.log('test33...');
            }
            console.log('test33声明后');
            test33();
        }

        function test4() {
            // test44(); // error  Cannot access 'test44' before initialization
            console.log('test44声明前');
            let test44 = function() {
                console.log('test44...');
            }
            console.log('test44声明后');
            test44();
        }
复制代码

闭包

闭包 = 函数 + 环境

闭包作为返回值

如下面这样, 在test5中定义的test55这个函数, 在该函数内部又使用了外部变量b, 然后将test55作为返回值return

那么test55函数和变量b就一块组成了闭包

        // 闭包作为返回值
        let a = 3;
        function test5() {
            let b = 5;
            function test55() {
                return b;
            }
            return test55;
        }
        console.log(test5()());
复制代码

闭包作为参数

而对于makeTimer这个函数, callback函数和msg形参形成闭包, 这个闭包作为实参被setTimeout调用

        // 闭包作为实参
        function makeTimer(msg) {
            function callback() {
                alert(msg);
            }
            setTimeout(callback, 2000);
        }
        makeTimer("shaosiming is nice");
复制代码

闭包作为事件处理程序

在下面代码中, button标签绑定了一个单击事件, 并且该事件中使用了count这个外部变量, 那么该事件处理程序和变量count就组成了闭包

<body>
    <div id="msg">你点击了0次</div>
    <button id="click">click me</button>
</body>
<script>
    window.onload = function() {
          let msg = document.getElementById('msg');
          let btn = document.getElementById('click');
          let count = 0;
          btn.onclick = function() {
              count++;
              msg.innerHTML = `你点击了${count}次`;
          }
    }
</script>
复制代码
分类:
前端
收藏成功!
已添加到「」, 点击更改