闭包

作用域链

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

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

定义三个变量 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

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


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容

  • 本章将会介绍 闭包表达式尾随闭包值捕获闭包是引用类型逃逸闭包自动闭包枚举语法使用Switch语句匹配枚举值关联值原...
    寒桥阅读 1,549评论 0 3
  • 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 一、变量...
    zock阅读 1,074评论 2 6
  • 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。 一、变量...
    zouCode阅读 1,269评论 0 13
  • 闭包: 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该...
    小裁缝sun阅读 610评论 0 5
  • 临近十一长假的前几天老公忽然兴奋的拿着手机让我看,我不以为然的喵了一眼我眼前一亮:原来是山东省东营市的黄河口风...
    胖胖胖016_cms阅读 232评论 0 0