JavaScript学习笔记——闭包—day three

目录

什么是闭包

两个经典逻辑案例

闭包的缺点

闭包的作用

1.实现公有变量

2.可以做缓存(存储结构)

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

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


什么是闭包

当内部函数被保存到外部时,将会生成闭包,生成闭包后,内部函数依旧可以访问其所在的外部函数的变量。

两个经典逻辑案例

例一

      function test() {
            var a = [];
            for (var i = 0; i < 10; i++) {
                a[i] = function () {
                    document.write(i + " ");
                }
            }
            return a;
        }
        var myArr = test();
        for(var j=0;j<10;j++)
        {
            myArr[j]();
        }

运行结果:10 10 10 10 10 10 10 10 10 10

10个10,经过for循环后 i=10,而return a 只是返回了函数内容(document.write(i + " ");)这里的 i 就一直是10。

例二

这也是闭包的解决和防范方法:将 i(或者需要的变量等,但凡牵涉到索引的问题,一定要注意)变现。

       function test(){
            var arr=[];
            for(i=0;i<10;i++)
            {
                (function(j){
                   arr[j]=function(){
                    document.write(j+" ");
                   }
                }(i))
            }
           return arr;
        }
        var myArr=test();
        for(j=0;j<10;j++)
        {
            myArr[j]();
        }

运行结果:0 1 2 3 4 5 6 7 8 9

闭包的缺点

闭包会导致原有作用域链不释放,造成内存泄漏(被占用了,剩下的内存不是理论上应该多大的内存,并不是字面意思的泄漏)

闭包的作用

1.实现公有变量

如:函数累加器

 function a(){
            var num=100;
            function b(){
                num++;
            console.log(num);
            }
            return b;
        }
        var add=a();
        add();
        add();
        add();

2.可以做缓存(存储结构)

例1

        function test() {
            var num = 100;

            function a() {
                num++;
                console.log(num);
            }
            // a defined   a.[[scope]]    0:testAo
            //                            1:GO
            function b() {
                num--;
                console.log(num);
            }
            // a defined   a.[[scope]]    0:testAo
            //                             1:GO
            return [a, b];
        }
        var myArr = test();
        myArr[0]();
        // 代表a
        //  a doing   a.[[scope]]    0:aAO
        //                           1:testAo(函数结束,AO依旧保留)
        //                           2:GO
        myArr[1]();
        // 代表b
        //  b doing   b.[[scope]]    0:bAO
        //                           1:testAo(上一步更改过后的testAO)
        //                           2:GO

运行结果:101  100   两个并列的函数使用的是同一个num,即一个testAO。

例二

       function eater() {
            var food = "";
            var obj = {
                eat: function () {
                    console.log("i am eating " + food);
                    food = "";
                },
                push: function (myFood) {
                    food = myFood;
                }
            }
            return obj;
        }
        var eaters = eater();
        eaters.push('banana');
        eaters.eat();

结果打印:i am eating banana  。这里面的food就相当于一个存储结构。对象里面包含两个函数,返回对象相当于返回两个函数。两个函数改变的始终都是同一个变量。

多个函数闭包,公用同一个变量。这种方式相当于缓存。

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

如:

        function Wang(name,old){
            var money=10000;
            this.name=name;
            this.old=old;
            this.save=function(){
                money++;
                console.log(money);
            }
        }
        var wang=new Wang('haha',46);

这里的money就相当于一个私有属性,不能直接访问。

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

命名空间问题

管理变量,即使两个函数中的变量名、函数名相同也不互相影响。开发的一个功能,以后会复用,就把它保存到一个闭包里面。

        var name = '123';
        var init=(function(){
            var name='456';
            function callName(){
                console.log(name);
            }
            return function(){
                callName();
            }
        }())
        var initWang=(function(){
            var name='789';
            function callName(){
                console.log(name);
            }
            return function(){
                callName();
            }
        }())

猜你喜欢

转载自blog.csdn.net/qq_38395419/article/details/83864291