闭包:搞定闭包-闭包体系完整梳理

前言:
问君能有几多愁,恰似答过闭包后面试官摇摇头 -- 沃 · 兹机硕德

闭包这个东西 , 面试之中必备的问题之一 , JavaScript 最关键的底层原理之一 ,无论是从哪个角度上来说,如果想要进阶为一个资深jser ,那么你都需要完全理解闭包这个东西。现在在网上存在非常多的闭包教程,但是我个人的感觉大多都是些在半路上进行讲解的教程,即使背下来也没办法理解,故而在开发中或者在面试官连续的提问之中真的把问题说出个所以然,那么本篇教程的主要目的就是从根源上把闭包的一整套知识体系梳理给大家,所以这篇文章闭包是标题,但是我更认为这是对一整套JavaScript程序底层体系的讲解。

运行一个函数

函数大家肯定熟悉,要是这个东西你真的不理解的话,请先买本高级程序看看然后再来看这篇文章,你以为我要说函数 ? 不不不, 我说要说的是你知道函数在被调用时发生了什么不? 这就是一个函数:

function foo(){
        var hello = "hello world";
        console.log(hello);
}
// 调用函数 
foo()

ok , 就这么一段代码他做了什么,我不用说,你也知道,不就是打印了 hello world 的一个简单函数么,对但是 too yuang too easy , 你知道咱们浏览器的解析器做了些啥不 ? 每段程序的执行都是硬件配合软件最终呈现的结果 , 这之中有个非常非常非常重要的东西 内存

什么是内存那 ?

这货就是内存


图片来源京东,侵删

你所有的代码在执行的时候都会被塞进这里,在本篇文章中你只需要理解到这里就可以了,如果需要继续理解我会再单独写一篇关于内存的专题。

ok 我们接着来说,往里面塞数据这个事,究竟怎么塞, 内部的结构是什么样的?

栈你可以理解为一个开口向上的容器,我们将数据在开口处放置进去,数据则自然下落到结构底部,所以数据在栈中的顺序是从下至上的,从底至上的数据下标分别为 0 , 1 , 2 ... 当数据已经用完了,程序发出指令需要清空栈内存之中的数据时我们删除的顺序是自顶部向下删除的,顺序为 ... 2 , 1 , 0 。由此我们可以得到规律栈内存数据我们遵循的数据是先进来的数据最后释放出去,我们称此为 FILO (first in last out), 简称先后出。如果你感觉这个文字看起来非常难以理解,请看这个动图,动图中黑色的为栈结构,红色的表示数据,能更直观的帮你去理解这个结构,当然内存并不只是有一种结构还有一种树形结构叫做堆,我们在此不赘述其原理,因为暂时用不到。

栈模型

@w=200h=200

活动对象-AO(Active Object)

上文说到一个非常重要的概念,就是所有程序在执行时都会和内存产生关联,JavaScript之中函数执行的时候也会和内存产生很多关联, 这个关联我们现在也只关注一点,就是函数执行时我们内存里面会储存些啥。

当函数执行的时候,我们的程序为了记录函数内部的变量,所以会找一块空间对这部分数据进行一个临时的存储,在使用结束之后,如果没用了就删除掉这部分数据。这部分数据如果我们用JavaScript进行表达的话,最好的结构就是对象,我们以对象的形式对其进行存储和表示 :

image.png

我们再用代码去说明一下:

function foo(){
        var hello = "hello world";
        console.log(hello);
}
foo()
// 只要是foo() 这段代码被解析器解析了,那么调用内存这事就开始了。

// 1. 解析器会在内存之中创建一个临时活动对象:

var _temp_Active_Object_foo = {}

// 2. 解析器在解析内部代码 var hello = "hello world"时,会在这个对象上添加一个属性,hello  值为 "hello world";

_temp_Active_Object_foo.hello = "hello world";

// 3. 解析器在解析内部代码console.log(hello),检索到了hello变量的引用,虽然看起来我们是在使用hello变量可是实际上我们引用的是活动对象之中的属性:

console.log(_temp_Active_Object_foo.hello);

//4. 函数执行完毕,在栈内存之中释放掉这个活动对象 

delete window._temp_Active_Object_foo

好了,这下我们把这个内容大概说清楚了,如果没有看明白建议仔细阅读流程图和代码,直到你把这两部分的内容完全记忆下来,这样你就可以继续进行下面的学习了,你距离学会整套闭包的体系还有一步之遥

两个函数的嵌套

ok,根据前面的知识讲解,我们已经明白了一个函数执行起来配合内存会做哪些事情,可是总会感觉学习这些东西有啥用,其实你可以把这些知识模块当成是一个又一个的乐高积木我们正努力把这些东西组装成我们想要的结构。

回到主题,我们现在要去研究的就是两个函数的嵌套,外部函数我们取名 outer , 内部函数我们取名inner :

    function outer(){
        function inner(){
        }
    }
    outer()

结构上大体定在这里,我们根据上面所学简单发散一下我们的思维,在外部函数执行的时候我们做了哪些事情。

    function outer(){
        function inner(){
        }
    }
    outer()
    //1.在内存之中创建一个活动对象 
    var _temp_Active_Object_outer = {};
    //2.在这个活动对象上去放一个属性
    _temp_Active_Object_outer.inner = function(){}

总结下这段代码 : 一个活动对象之中放入了一个函数(引用类型),而不再是具体的值 , 这又有什么关系那。你可不能忘了,这个活动对象是怎么生成的,是由函数生成的,也就是说这个活动对象之中存在一个可以创建活动对象的玩意。可以这么理解,平日里你家人给你发生活费的时候就一个红包,点一下收一次钱就可以了,这次给你发的红包点完开之后不仅显示收钱了,又给你弹出一个新的红包,上面写着个开,你要不要点 ? 点了红包就打开了潘多拉魔盒,发现了新大陆,原来红包还可以这么玩?

是啊,函数还可以这么玩。

好的让我们再进一步 :

   function outer(){
        //新增一个外部函数中的变量
        var freeVar = "something"
        function inner(){
            //在内部函数引用freeVar
            console.log(freeVar);
        }
        // 最后将这个结果返回
        return inner
    }
    //在外部接受代码
   var inner =  outer()

其实在这个时候,我们已经使用了闭包,为什么那?简单来说闭包其实就是:

  1. 在外部函数声明的变量在内部函数被引用了
  2. 在外部函数的时候,把内部函数返回出去,在全局接收。

简单的理解先到这里,下次我会谈一谈关于闭包的实际应用及学习内存部分知识的意义。

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