day14 回调函数 匿名函数 闭包 模拟私有变量 同步 异步

回调函数:

执行完一个动作之后还要继续执行的函数

作为实参传递的函数就是回调函数

function a() {
    console.log(123);
}


function b(fn) {
    // fn: 形参 函数 回调函数
    console.log(fn);
    fn();
}
b(a);

匿名函数

匿名: 没有名字的函数

直接写会报错 将匿名函数转换成函数表达式 外面加() 同样具有函数的特点

立即执行函数: IIFE

  1. 函数自执行

    使用: 团队协作

    注意: 分号必须加 不能省略

    (function () {
        console.log('匿名函数');
    })();
    
    (function () {
        console.log('匿名函数1');
    }());

    有参数

    (function (a, b) {
        console.log(a, b);
        console.log(arguments);
    })(10, 20);

    有函数返回值

        var res = (function () {
            return true;
        })();
        console.log(res);

    闭包

    概念

    闭包: 可以访问其他函数内部变量的函数就是闭包

    组成: 函数里面套函数 内部函数访问外部函数的变量

    优点: 扩大变量的作用范围 缓存数据

    缺点: 如果有大量缓存数据 会造成内存泄漏 不参与垃圾回收机制

    调试:

    使用断点调试

    \1. outer的第一行代码

    \2. inner的第一行代码

    \3. 刷新 看右侧或者底部的 Scope

    local: 当前作用域

    Global: 全局

    closure: 闭包

    注意: 外部函数调用一次就会形成一个新的闭包

    function outer() {
        var a = 10;
        function inner() {
            a++;
            console.log(a);
        }
        // 设置返回值
        return inner;
    }
    var res = outer();
    console.log(res); // inner函数
    res(); // 11
    res(); // 12
    
    // 外部函数调用一次就会形成一个新的闭包
    var res1 = outer();
    res1();

    使用

    当当前作用域需要自己的变量值的时候 使用闭包

    在for循环所添加的事件中 解决不能通过下标得到正确的元素的问题

    var lis = document.querySelectorAll('li');
    console.log(lis);
    // for(var i = 0; i < lis.length; i++){
    //     lis[i].onclick = function () {
    //         console.log(i); // 10
    //     };
    // }
    
    for(var i = 0; i < lis.length; i++){
        (function (s) {
            // console.log(s);
            lis[s].onclick = function () {
                console.log(s);
            };
        })(i);
    }

    模拟私有变量

    // 创建账号
    function create(val) {
        var user = val;
        // console.log(user);
        // 如果想要在函数外读取或者设置 必须通过当前函数提供的专用函数来实现效果
        return {
            getUser: function () {
                console.log(user);
            },
            setUser: function (v) {
                user = v;
            }
        };
    }
    var u = create('小时候超白');
    console.log(u);
    u.getUser();
    u.setUser('长大后超黑');
    u.getUser();
    
    // 与上面的user无关
    user = '中年时候超胖';
    console.log(user);
    u.getUser();

    面试题

  2. 输出结果

    function fun(n, o) {
        console.log(o);
        return {
            "fun": function (m) {
                return fun(m, n);
            }
        }
    }
    /* 
        var a = fun(n, o)--> fun(0) --> n = 0 o = undefined
        a = {fun: function(m){  }}
            a.fun(1)
                m = 1 fun(m, n)  m = 1  n = 0  fun(1, 0) --> fun(n, o) n = 1 o = 0 log(o) --> 0
            a.fun(2)
                m = 2 fun(m, n) m = 2 n = 0 fun(2, 0) --> fun(n, o) n = 2 o = 0 log(o) --> 0
            a.fun(3)
                m = 3 fun(m, n) m = 3 n = 0 fun(3, 0) --> fun(n, o) n = 3 o = 0 log(o) --> 0
    
    */
    var a = fun(0); // undefined
    a.fun(1);  // 0
    a.fun(2); // 0
    a.fun(3); // 0

    输出结果和执行顺序

    for(var i = 0; i < 5; i++){
        setTimeout(function () {
            console.log(i, new Date(), new Date().getTime()); // 5 当前时间+1s
        }, 1000);
    }
    console.log(i, new Date()); // 5 
    /* 
        同步: 当前代码执行的时候 后续的代码等着 alert for
        异步: 当前代码执行的时候 后续代码不等待执行完成 就可以直接执行 定时器
    */

    代码分类

    同步: 当前代码执行的时候 后续的代码等着 alert for

    异步: 当前代码执行的时候 后续代码不等待执行完成 就可以直接执行 定时器

上一篇:ECS34 SQ19


下一篇:day14 异常