美文网首页
JavaScript闭包

JavaScript闭包

作者: 追逐_e6cf | 来源:发表于2019-02-16 14:00 被阅读0次

    一、获取局部作用域的变量

    1. 通过变量向外传递。
    2. 通过函数向外传递。
    3. 条件和循环体:{}不代表作用域,在es6语法中,{}会被看做代码块,此时在{}当中声明一个函数,相当于var声明,尽量不要在{}当中声明函数,否则调用的时候会有问题。
    // 通过变量 向外传递    
    var b = '';
    function fn1(){
        var a = "月薪10w";
        b = a;
    }
    fn1();
    alert(b); //取到函数内局部作用域的变量a的值
    
    // 通过函数传参获取
    function fn1(){
        var a = "月薪10w";
        fn2(a);
    }
    function fn2(str){
        alert(str);
    }
    fn1();
    
    alert(fn1); //undefined
    {
        function fn1(){
            alert(1);
        }
    }   
    

    二、闭包

    1. js垃圾回收机制:js 中的变量和函数不再使用后,会被自动js垃圾回收机制回收。
    2. 形成闭包的条件:有函数/作用域的嵌套;内部函数引用外部函数的变量/参数。
    3. 闭包的结果:内部函数的使用外部函数的那些变量和参数仍然会保存,使用return返回了此内部函数,上面的变量和参数不会被回收。
    4. 闭包的原因:返回的函数并非孤立的函数,而是连同周围的环境(AO)打了一个包,成了一个封闭的环境包,共同返回出来 ---->闭包。
    5. 我们在返回函数的时候,并不是单纯的返回了一个函数,我们把该函数连同他的AO链一起返回了。
    6. 函数的作用域,取决于声明时而不取决于调用时。
    7. 变量存储function(){}{}[]存储的是一个地址。
    function t1(){
        var age = 20;
        function t2(){
            alert(age);
        }
        return t2;
    }
    var tmp = t1();
    var age = 1000;
    tmp(); //20
    
    // win 1. AO{t1:function(){},tmp:un,age:un}
    //     2. t1     1. AO{age:un,t2:fun}
    //               2. AO{age:20,t2:fn}
    //        AO{t1:function(){},tmp:t2,age:1000}
    //      
    //        tmp  t2 1.AO{}
    
    var age = 10;
    function t1(){
        var age = 20;
        return function t2(){
            alert(++age);
        }
    }
    var t3 = t1();
    t3(); // 21
    t3(); // 22
    t3(); // 23
    alert(age); //10
    
    var age = 10;
    function t1(){
        var age = 20;
        return function t2(){
            alert(++age);
        }
    }
    var t3 = t1();
    var t4 = t1();
    t3(); //21
    t4(); //21
    
    function foo(){
        var a = 2;
        function baz(){
            console.log(a);
        }
        bar(baz);
    }
    function bar(fn){
        var a = 3;
        fn();
    }
    foo();
    //2
    

    三、闭包计数器

    使用js的命名空间,优点:变量不受污染。

    <script>
        var chengming = {};//js的命名空间 一般就是这么写
        chengming.inc = (function(){
            var cnt = 0;
            return function(){
                return ++cnt;
            }
        })();
    
        console.log(chengming.inc());
    </script>
    <script>
        var cnt = 100;
        console.log(inc()); //报错,window下访问不到inc
    </script>
    

    四、循环中的闭包

    <body>
        <input type="button" name="" value="按钮1">
        <input type="button" name="" value="按钮2">
        <input type="button" name="" value="按钮3">
    </body>
    <script>
        var inp = document.getElementsByTagName('input');
        for(var i=0; i<inp.length; i++){
            inp[i].onclick = function(){
                inp[i].style.background = "yellow";
            }
        }
        //点击按钮会报错,因为i在window全局上,for结束之后,本身的值就是3
    </script>
    
    // 方法一  用自定义属性
    for(var i=0;i<inp.length;i++){
        inp[i].i = i;
        inp[i].onclick = function(){
            inp[this.i].style.background = 'yellow';
        }
    }
    
    // 方法一  用let关键字
    for(let i=0; i<inp.length; i++){
        inp[i].onclick = function(){
            inp[i].style.background = "yellow";
        }
    }
    
    // 方法三 使用this
    for(var i=0; i<inp.length; i++){
        inp[i].onclick = function(){
            this.style.background = "yellow";
        }
    }
    
    // 方法四  for循环每次执行,都会立即执行一个匿名函数,并且匿名函数的作用域中传入了当时的i作为参数传递
    for(var i=0; i<inp.length; i++){
        (function(i){
            // AO{i:1}
            inp[i].onclick = function(){
                // AO:{}
                inp[i].style.background = 'yellow';     
            }
        })(i)
    }
    
    // 方法五
    for(var i=0; i<inp.length; i++){
        (function(){
            // AO{}
            var arg = i;
            inp[arg].onclick = function(){
                // AO:{}
                inp[arg].style.background = 'yellow';
            }
        })()
    }
    
    // 方法六
    for(var i=0; i<inp.length; i++){
        inp[i].onclick = function(i){
            // AO:{i:0}
            return function(){
                inp[i].style.background = 'yellow';
            }
        }(i)
    }
    
    // 方法七
    for(var i=0; i<inp.length; i++){
        (inp[i].onclick = function(){
            inp[arguments.callee.i].style.background = 'yellow';
        }).i = i;
    }
    
    // 方法八九 基本包装类型
    for(var i=0; i<inp.length; i++){
        inp[i].onclick = new Function(`inp[${i}].style.background = 'yellow';`);
    }
    for(var i=0; i<inp.length; i++){
        inp[i].onclick = Function(`inp[${i}].style.background = 'yellow';`);
    }
    

    相关文章

      网友评论

          本文标题:JavaScript闭包

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