闭包

作者: nwzk41 | 来源:发表于2016-12-10 11:08 被阅读0次

作用域链

要学习闭包,首先要了解作用域链

作用域链:环境对象中定义的变量,会放到作用域中,形成一个链式结构。

定义三个变量 a b c 使其在不同的作用域

var a = 10;
        function F() {
            var b = 20;
            //内部函数:函数内部定义的函数
            function N() {
                var c = 30;
                return a + b + c;
            }
            return N();
        }
        

        //验证N中是否都能使用所有的链上变量
        console.log(F());//60

在变量 c 的作用域中,可以调用到 a b 在 b 的作用域中,可以调用到 a
但是反向就不能实现,a 的作用域中无法调用 b c ,b的作用域中 无法调用 c

如果我们想在变量作用域中访问其子作用域中定义的变量,要怎样实现呢?闭包的使用能解决这个问题


利用闭包突破作用域链

首先来看闭包的概念

闭包的概念、优点、缺点.png

闭包的原理就是在被访问的变量a的作用域中创建一个函数,将需要访问的变量当做新创建的函数返回值,再将函数定义给最外层的变量b,就能通过执行变量b来访问到变量a

原理如图:

利用闭包突破作用域链.png

代码如下:

//第一种写法
var a = 10;
        function F() {
            var b = 20;
            function N(){
                return b
            }
            return N;
        }
        var M = F();
        console.log(M());

        // 原理一样,写法不一样,第二种写法
        var inner;
        var a = 10;
        function F() {
            var b = 20;
            function N(){
                return b
            }
            inner = N;
        }
        F();
        console.log(inner());

不过需要注意:

闭包会常驻内存,使用需要谨慎

闭包的概念清楚了,下面来讲一下闭包的应用


闭包的应用1

循环中的闭包

我们可以试着将函数里循环中的每一个变量拿出来。

敲一下代码:

 function F() {
            var arr = [];

            for (var i = 0; i < 3; i++) {
                arr[i] = function(){
                    return i;
                };
            }
            return arr;
         }

         var str = F();

         console.log(str[0](), str[1](), str[2]());//3 3 3 

咦?什么鬼,怎么出现了三个一样的数

分析一下,不难发现,arr[i]中保存的是 i , i 是相当于直接定义在 F 函数的作用域中,执行完 F 函数 i 的值直接就已经变为 3 ,这样,我们就应该在循环的时候,就把数组里的值保存下来,这样就对了

闭包本身不保存上一作用域中变量的值,当使用时是去上面的作用域中查找相同名字变量,使用最近那一层作用域中的变量

修改代码如下:

function F() {
            var arr = [];

            for (var i = 0; i < 3; i++) {
                arr[i] = (function(x){
                    return function(){
                        return x;
                    };
                })(i);
            }
            return arr;
        }

        var str = F();

        console.log(str[0](), str[1](), str[2]());//0 1 2

也有原理图,在此:

2.png

这样就能保存到我们想要的数据了


闭包的应用2

getter 和 setter

有时候,为了变量的安全考虑,我们一般会不让变量直接被访问到
就可以利用闭包来实现

看看代码:

var setNum;
var getNum;


        (function(){
            var num = 0;

            //setter方法
            setNum = function(x) {
                //安全的考虑
                if (typeof x === "number") {
                    num = x;
                }
            };

            //getter方法
            getNum = function() {
                return num;
            };

        })();

        console.log(num);//0

        setNum(100);
        console.log(getNum());//100

这样的话,直接访问 num 是访问不到的,同时要修改 num 的值也不能直接修改,通过闭包的方法,我们还能控制赋给变量新赋值的类型


闭包的应用3

迭代器

迭代: 一个一个寻找下一个目标

知道遍历简单的数组,以后便利的数据结构可能比较复杂

使用“下一个是谁”的想法去遍历

代码如下:

var arr  = [1,2,3,4,5];

        function setUp(x) {
            var i = 0;
            return function (){
                if(x.length == i-1){
                    i = 0;
                }
                return x[i++];
            }
        }

        var next = setUp(arr);
        console.log(next());//1
        console.log(next());//2
        console.log(next());//3
        console.log(next());//4
        console.log(next());//5

        console.log(next());//undefined
        console.log(next());//1
        console.log(next());//2

这样就实现了迭代的方法,一次一次找到下一个值


相关文章

  • swift-闭包

    闭包 闭包定义 闭包简化 - 尾随闭包 闭包参数 闭包返回值 闭包的循环引用

  • 闭包,闭包,闭包

    1、这家伙到底是什么? 网上关于这个的讨论的太多了太多了,有各种的举例子,但是大部分还在寻找这个答案的小伙伴对于变...

  • 闭包-Closures [swift 5.1]

    闭包的语法 尾随闭包 闭包逃离 自动闭包

  • Day7 闭包(Closures)

    本页包含内容:• 闭包表达式• 尾随闭包• 值捕获• 闭包是引用类型• 逃逸闭包• 自动闭包 1、闭包表达式 闭包...

  • Python闭包

    闭包 = 环境变量 + 函数 调用闭包内部的环境变量 闭包的经典误区 闭包与非闭包实现人类走路 非闭包 闭包

  • 闭包(closure)

    ● 闭包基础 ● 闭包作用 ● 闭包经典例子 ● 闭包应用 ● 闭包缺点 ● 参考资料 1、闭包基础 作用域和作...

  • swift- 闭包一

    /*• 闭包表达式• 尾随闭包• 值捕获• 闭包是引用类型• 逃逸闭包• 自动闭包*/

  • (9) python之闭包

    闭包闭包 = 函数 + 环境变量(函数定义的时候) 一个最简单的闭包 闭包不受外部变量影响 非闭包 闭包 闭包 只...

  • Swift-进阶 :闭包(二)逃逸闭包 & 非逃逸闭包

    本文主要分析逃逸闭包 、非逃逸闭包、自动闭包 逃逸闭包 & 非逃逸闭包 逃逸闭包定义 当闭包作为一个实际参数传递给...

  • javascript闭包详解

    跟我念 bi 闭 bao包 ,闭包的闭,闭包的包。。 闭包的简介 在计算机科学中,闭包(英语:Closure),又...

网友评论

      本文标题:闭包

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