再谈JS闭包(JS闭包系列2)

这篇文章,来继续谈谈Javascript闭包的剩余问题。因为在上一篇文章中关于JS闭包(JS闭包系列1)主要简单的示例代码直观的观察了下闭包,这篇文章就来从理论上好好地分析分析JS闭包的有关概念。

首先应该知道的是JS中的作用域链(scope chain)概念:

(1)定义
每个人都有自己的生活环境,代码也一样,JS中的代码都有自己的“执行环境”。当代码在一个环境中定义时(函数调用之前),就会生成变量对象的作用域链。这个链条,从当前环境中的变量对象开始,上溯至父环境(包含环境)中的变量对象,再到父环境的父环境中的变量对象···一直上溯到全局执行环境的变量对象。想象着一条锁链,从最下面开始爬,一直爬到最上顶端。每一个节点,代表着这一层级环境中的变量对象。

需要注意的是,作用域链是根据 函数定义 时的位置确定的,而不是在调用时确定。这也叫做 词法作用域

chain

(2)作用
作用域链用来保证那些有权访问不同执行环境的代码,在对不同环境里的变量和函数访问时的有序性以及确定性

(3)应用
当解析一个标识符时,是沿着作用域链一级一级地上溯(回溯)搜索标识符的过程。如果找不到标识符,就会产生错误。

还是直接看代码吧:

var color = "blue";  //全局作用域
function changeColor(){
    if(color === "blue"){ //寻找`color`,此作用域(函数内)没有,则上溯到父级作用域,(这里是全局)找到了
          color = "red";
    }else{
          color = "blue";
    }
}
changeColor();
alert("Color is now " + color);

在这个例子中,函数changeColor的作用域链包含两个对象:它自己的变量对象(每个函数都有的arguments对象),以及全局环境中的变量对象。

再来看一个多层作用域链示例:

var weibing = "在";  //最外层守卫
var dajiangjun = "不在";  //2号大将军
function chengqiang(){  //城墙内
    var dajiangjun= "在";  //1号大将军
    function gongdian(){  //宫殿内
        var zaixiang = "不在";  //宰相
        if(zaixiang === "在")
             console.log("把宰相找来!");
        else if(dajiangjun === "在")
             console.log("把大将军找来!");
        else
             console.log("把卫兵找来!");
    }
     return gongdian();
}
 chengqiang();    

结果可想而知:


皇帝召见层级

想象这样一个场景:皇帝身居寝宫,寂寞了,想要招纳美女。那么首先想到的是宰相,他可以直接召见宰相,让宰相给自己办事。假如宰相不在,那么他可以召见大将军(职级低于宰相),让大将军给自己干;碰巧,大将军也去喝酒了,那就直接召见卫兵。在这个例子中,皇帝找到大将军了。但是有人会问,这段代码里,有两个dajiangjun啊!对啊,可是,皇帝他老人家是从自己身边找人的。最外边的那个2号大将军,虽然也在,但是他没上朝,去考察去了。(没在城墙内),所以就召见1号大将军喽。而且自然而然,在城墙外边的人(例如普通老百姓),当然是见不到宰相和皇帝的啦。
例如在上面代码下面加如下代码:

function chixinwangxiang(){ //痴心妄想
      alert("把"+zaixiang+"给爷叫出来!");
}

结果是:


痴心妄想

在城墙外边,你肯定是见不到一人之下,万人之上的宰相大人啦!

(4)注意
因为在JS中,作用域里没有以花括号包围的“块级作用域”概念,看一个例子:

if(true){
    var a = 1;
}
console.log(a);  //输出1

表面上看来, a在if语句里面定义着,那么console语句应该是访问不了的,然而事实恰恰相反,因为在JS中,if或者for语句的花括号,根本不是独立作用域,只有函数的花括号才起作用。

总结:现在知道了作用域链的概念,而你应该知道的是,闭包就是由作用域链引起的。下一节,就要带着作用域链的思维来思考闭包,那样就简单多了。因为你会发现那是顺其自然。

本篇完

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

推荐阅读更多精彩内容