美文网首页
成长(8/2000)——面试题合集5

成长(8/2000)——面试题合集5

作者: Kiki_Q | 来源:发表于2021-06-11 18:12 被阅读0次

    闭包的底层原理

    闭包的底层原理其实就是作用域链被保存下来的原因,具体往下看

    作用域链

    • 之前我们讲作用域和预编译的时候,函数作用域会创建AO对象,全局作用域会创建GO对象,它们会被保存到一个隐式的属性[[scope]] 中去,这个属性是我们访问不到的,但是是的的确确存在的熟悉,是给js引擎访问的,里面存储的是AO和GO的集合

    要点:

    • 函数定义的时候会形成作用域链,但是函数执行完就会断开作用域链
    • 外层函数的执行和其内层函数的定义的作用域链是相同的(精髓点,当外执行完成后销毁,内层定义其实还是保存着这条作用域链的,所以仍能访问相应的变量)
    var global;
    function a() {
        function b() {
            var bb = 123;
            aa = 0;
        }
        var aa = 123;
        b();
    }
    
    a()  //第一个a函数
    a() //第二个a函数
    
    a定义

    第一个a函数执行前会先定义,定义的时候会产生它的作用域链,因为是全局函数,所以会产生GO,可以看出只有global和a函数;

    a执行

    当a函数执行的时候会产生它自己的AO对象(函数作用域),如图,aa变量和b函数;

    以上讲述了函数中作用域链的产生方式;注意当第二个a函数执行他会有他自己的作用域链,它们之间是互不影响的!

    下面我们通过以下函数说明闭包的原理:

    function a() {
        var aa = 123;
        function b() {
            var bb = 234;
            console.log(aa)
        }
        return b;
    }
    
    var res = a();
    res();
    
    Scope1.png Scope2.png Scope3.png

    就看图1和2就可以,a执行和b定义的作用域链是一样的,a执行完会断开自己的作用域链,但是此时b定义的作用域链仍存在;闭包返回的是函数,此时还未执行,属于定义阶段,所以可以访问作用域链上的变量

    闭包的运用

    • 单例模式
      当多个地方调用同一个能力模块,我们只需要产生一个实例即可。(例如多个地方需要弹出弹框,实际页面只需要产出同一个弹窗即可)
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <button id="loginBtn">登录</button>
    </body>
    <script>
        
        let createLogin = function () {
            let div = document.createElement("div");
            div.innerHTML = "这是登录弹窗";
            div.style.display = "none";
            document.body.appendChild(div);
            return div;
        }
    
        let getSingle = function (fn) {
            var result;
            return function () {
                return result || ( result = fn.apply(this, arguments) )
            }
        }
    
        let create = getSingle(createLogin);
    
        document.getElementById("loginBtn").onclick = function () {
            let loginLay = create();
            loginLay.style.display = "block";
        }
    </script>
    </html>
    

    相关文章

      网友评论

          本文标题:成长(8/2000)——面试题合集5

          本文链接:https://www.haomeiwen.com/subject/jtdveltx.html