js闭包问题以及解决办法

个人理解闭包的产生主要就是:一切最外部的函数比里面的函数先执行,必然产生闭包,闭包会导致原有的作用域链不释放,造成内存泄漏

 

例子1

解析:实现上现在的demo保存的是function b()  a执行之后就销魂了自身的AO,但是此时b已经保存了a的AO

 <script>
    function a() {
        var num = 100;

        function b() {
            num++;
            console.log(num);

        }
        return b; //b还没有被立即执行就直接返回了
    }
    // a先执行完  执行完销毁自身的ao

    var demo = a();
    demo(); //101
    demo(); //102
    demo(); //103
</script>


<!-- 等同于 -->
<!-- <script>
    function a() {
        var num = 100;

        // function b() {
        //     num++;
        //     console.log(num);
        // }     
        // b(); //101
        // b(); //102
        // b(); //103

        for (var i = 0; i < 3; i++) {
            function b() {
                num++;
                console.log(num);
            }
            b();
        }
    }

    a();
</script> -->

 

例子2

解析:为什么可以打印出123?因为函数内部的b函数并没有执行而是被保存到了外部,a函数先执行此时的aaa已经是123了,b又保存了a的执行期上下文

<script>
    function a() {
        function b() {
            console.log(aaa);
        }
        var aaa = 123;
        return b;
    }
    var result = a();
    result(); //123
</script>

例子3

<script>
    function text() {
        var arr = [];
        for (var i = 0; i < 10; i++) {
            arr[i] = function () {
                console.log(i);
            }  //还没执行 这一步就是相当于赋值 此时console.log(i)里的i看成一个i变量就行  等函数执行的时候再从作用域链里拿值
        }
        return arr;

    }
    var myarr = text();
    myarr[0](); //10
    myarr[1](); //10
    myarr[2](); //10

    // 分析:text()先执行的然后销毁了自身的AO,arr里的函数已经保留了text()里的AO,arr里的函数执行时从作用域里找i,找到9的时候还能进行循环 然后i++变成10直接return了
</script>

闭包的作用

1.实现共有变量(函数累加器)

 // 1111111111111111.
    function add() {
        var num = 0;
        function demo() {
            num++;
            console.log(num)
        }
        return demo();
    }
    var result = add();
    result();
    result();

2.可以做缓存

<script>
    // 2222222222222222.  缓存结构
    function test() {
        var num = 100;

        function a() {
            num++;
            console.log(num)
        }

        function b() {
            num--;
            console.log(num)
        }
        return [a, b];
    }

    var arr = test();
    arr[0](); //101   先执行a() 
    arr[0](); //102  
    arr[1](); //101   执行b()   拿到的num是已经改过的num
</script>

3.可以实现封装,属性私有化


<script>
function eater() {
        var food = "";
        var obj = {
            eat: function () {
                console.log("i am eating " + food)
            },
            food: "",
            push: function (myfood) {
                food = myfood;
            }
        }
        return obj;
    }
    var eater1 = eater();
    eater1.push('tea');
    eater1.eat();       // eat()     i am eating tea
</script> 

4.模块化开发,防止污染全局变量

<script>

    var name = 'hhh';
    var init = (function () {
        var name = 'abc';

        function callname() {
            console.log(name);

        }
        return function () {
            callname();
        }
    }())

    var initha = (function () {
        var name = 'tt';

        function callname() {
            console.log(name);

        }
        return function () {
            callname();
        }
    }())

    init(); //abc

    initha() //tt
</script>

 

闭包的解决方法

1.立即执行函数

 
function text() {
        var arr = [];
        for (var i = 0; i < 10; i++) {
            (function (a) {
                arr[a] = function () {
                    console.log(a);
                } //保存的是立即执行函数的成果AO()
            }(i))

        }

        return arr;
    }

    var myarr = text();
    myarr[0](); //0
    myarr[1](); //1
    myarr[2](); //2

2.ES6 let声明变量----let定义变量

 function text() {
        var arr = [];
        for (let i = 0; i < 10; i++) {
            arr[i] = function () {
                console.log(i);
            }
        }
        return arr;
    }

    var myarr = text();
    myarr[0]();  //0
    myarr[1]();  //1
    myarr[2]();  //2

 

  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值