变量对象和活动对象

变量对象:包含函数内部的所有变量和函数
活动对象:函数调用了,函数中才会有活动对象,否则只有“处于静止状态”的变量对象,当然也没有创建执行环境。

以下转载自:https://www.zhihu.com/question/36393048
js 中的活动对象 与 变量对象 什么区别?
<meta charset="utf-8">

作者:闭家锁
链接:https://www.zhihu.com/question/36393048/answer/71879330
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

在回答这道题的时候,我也是抱着总结的目的来学习的,因为遇到了某些疑问所以最近一直在温习闭包、执行环境与作用域以及function引用类型的知识。

鉴于题主没有问题描述,那么我姑且认为题主具有初级以上的JS语法知识熟悉作用域和执行环境乃至闭包,我也认为题主应该知道变量对象就是执行环境中包含了所有变量函数的对象。另外变量对象是后台的,保存在内存中的,代码无法直接访问的。

假设在全局环境下定义了函数pub()和变量pubvar:

var pubvar = 1;
function pub () {
  var pravar = 2;
  return pubvar + pravar;
}

alert(pub(2));     //调用pub()函数

此时后台会创建一个作用域链(scope chain),这个作用域链包含了全局环境的变量对象并被保存在pub()函数内部的scope属性中。但是,当我们打开浏览器的时候已经存在了一个全局的执行环境,这个全局的执行环境属于浏览器,JS里浏览器被称为window对象,我们把这个环境叫做A环境,只要没有关闭浏览器,A环境会一直存在下面会提到执行环境什么时候会被创建。
我们用色块表示执行环境,链条表示作用域链,作用域链上半部分是活动对象区域,下半部分是变量对象区域,如下图:

<figure>

<noscript><img src="https://pic1.zhimg.com/50/f20a5f2137716e4936490704018ddd27_hd.jpg" data-rawwidth="1754" data-rawheight="1240" class="origin_image zh-lightbox-thumb" width="1754" data-original="https://pic1.zhimg.com/f20a5f2137716e4936490704018ddd27_r.jpg"></noscript>

image

</figure>

当我们要调用pub()函数的时候,又会创建一个执行环境B,没错,执行环境如其名是在运行和执行代码的时候才存在的,所以我们运行浏览器的时候会创建全局的执行环境。这个时候根据pub()函数scope属性中的作用域链把pub()函数内的变量对象放入新的B环境中,作用域链也得到更新,如下图:

<figure>

<noscript><img src="https://pic4.zhimg.com/50/32541193ee5c7900e5137c245f4dfe32_hd.jpg" data-rawwidth="1754" data-rawheight="1240" class="origin_image zh-lightbox-thumb" width="1754" data-original="https://pic4.zhimg.com/32541193ee5c7900e5137c245f4dfe32_r.jpg"></noscript>

image

</figure>

上图的虚线表示正在执行,全局变量对象此时处于作用域链的第二位,所以标号变成了1。****你可能也注意到那个arguments对象,它是在函数被创建的时候就一直存在的,无需用户创建。arguments对象保存的是函数圆括号内定义的参数,准确来说保存的是参数的值,因这里我们没有设置参数,所以显示未定义。

此时我们把属于B环境的变量对象(也就是pub()函数中的所有函数和变量)叫做活动对象。

因此我们可以说变量对象包含了活动对象,活动对象就是作用域链上正在被执行和引用的变量对象。我们从活动对象的名称中也能看出 “执行、运行、激活” 等意味。你可以这样理解,整个代码的运行总有一个起始的对象吧,不管这个起始是变量还是函数,总要有一个称呼,虽然我们把执行环境中的变量和函数的总称叫做变量对象,但这不能反映代码的动态性,为了区别于普通的变量对象,我们创造了活动对象的概念。

这就完了?没有,上一段我们说到代码的动态性,所谓动态性在这里的意思是有些代码参与了运行,有些没有,就像高中的化学反应一样,总有一些化学物不会参与到整个反应中来。我们把上面的代码变成如下:

var pubvar = 1;
function pub () {
  var pravar = 2;
  return pubvar + pravar;
}

var pubvar2 = 3;
function pub2 () {
  var pravar = 2;
  return pubvar2 + pravar;
}

alert(pub(2));      //调用pub()函数

这个时候全局作用域链和执行环境如下:

<figure>

<noscript><img src="https://pic4.zhimg.com/50/ff0d8172b0e7fb6a86a2fbbbb1a20725_hd.jpg" data-rawwidth="1754" data-rawheight="1240" class="origin_image zh-lightbox-thumb" width="1754" data-original="https://pic4.zhimg.com/ff0d8172b0e7fb6a86a2fbbbb1a20725_r.jpg"></noscript>

image

</figure>

接着我们调用pub()函数,执行环境和作用域链如下:

<figure>

<noscript><img src="https://pic1.zhimg.com/50/6eacf5a4f59a2a2214557132ee277fea_hd.jpg" data-rawwidth="1754" data-rawheight="1240" class="origin_image zh-lightbox-thumb" width="1754" data-original="https://pic1.zhimg.com/6eacf5a4f59a2a2214557132ee277fea_r.jpg"></noscript>

image

</figure>

你看没有被调用的pub2()函数仍然只是闲着,甚至没有被pub()函数在内部引用。由于pub2()没有参与整个pub()函数的调用过程,所以pub2()中不存在活动对象,只有“处于静止状态”的变量对象,当然也没有创建执行环境。

到这里就完了?也没有,我们刚才也只是讨论了两个平行且毫不关联的函数其中一个被调用的状况,言下之意就是也存在函数相互影响的例子,最典型的就是闭包,闭包是一种函数嵌套的情况。
定义如下代码:

function returnfunc (propertyName) {
  return function (obj) {             //-----这行定义并返回了一个闭包,也被称之为一个匿名函数
    return obj[propertyName];         //这里用方括号法访问属性,因为属性是变量(returnfunc()函数的参数)
  };
}

var savefunc = returnfunc("name");     //调用returnfunc()
var result = savefunc({name:"Picasso"});//调用savefunc()
alert(result);                        //返回字符串“Picasso”

以上代码的最开始的作用域链和执行环境:

<figure>

<noscript><img src="https://pic4.zhimg.com/50/25496cbcbd8c00b19c593e10864246de_hd.jpg" data-rawwidth="1754" data-rawheight="1240" class="origin_image zh-lightbox-thumb" width="1754" data-original="https://pic4.zhimg.com/25496cbcbd8c00b19c593e10864246de_r.jpg"></noscript>

image

</figure>

我们先开始调用returnfunc()函数,马上会创建一个包含returnfunc()变量对象的行环境,作用域链开始变化,如下图:

<figure>

<noscript><img src="https://pic3.zhimg.com/50/2ffc8d20774434c2d55c105a0df33b91_hd.jpg" data-rawwidth="1754" data-rawheight="1240" class="origin_image zh-lightbox-thumb" width="1754" data-original="https://pic3.zhimg.com/2ffc8d20774434c2d55c105a0df33b91_r.jpg"></noscript>

image

</figure>

图的白色虚线表示执行程序产生的效果,它可能表示的是返回一个结果、复制某种值、产生一个新物体、建立某种联系等。
题外话:你会发现上图的arguments参数的值和propertyName的值是一样的,这是因为arguments保存的就是参数,采用实时映射的方式与参数建立联系,如果你在returnfunc()函数内再加一个值为{name:"picasso"},名为obj的参数,那么arguments的值变成[{name:"nicholas"},{name:picasso}],是的,你没看错,arguments是一个数组!!!

随后returnfunc()函数会返回它内部的匿名函数,当匿名函数被返回后,整个作用域链和执行环境又发生了变化:

<figure>

<noscript><img src="https://pic2.zhimg.com/50/8d03dda08f2405f6d46481734e9cb16c_hd.jpg" data-rawwidth="1754" data-rawheight="1240" class="origin_image zh-lightbox-thumb" width="1754" data-original="https://pic2.zhimg.com/8d03dda08f2405f6d46481734e9cb16c_r.jpg"></noscript>

image

</figure>

我们看到匿名函数(闭包)被添加到了最作用域链的最前端,returnfunc()的执行环境被销毁,但我们注意到****returnfunc()函数的活动对象仍然在被引用(匿名函数仍在访问propertyName参数)****,因此****returnfunc()函数的变量对象仍然在内存中,成为活动对象。这就是为什么匿名函数就能访问returnfunc()函数定义的所有变量和全局环境定义的变量,毕竟returnfunc()的活动对象仍然保持“激活”状态。

根据上面所述,随着代码一行一行的被执行、执行环境不断被创建和销毁、变量对象间的各种关系被建立,这些背后的逻辑导致活动对象也在不断变化,这足以证明活动对象只是正在被执行和引用的变量对象。

我个人的理解是:活动对象是按照状态划分的一类变量对象,你也可以根据变量对象被调用次数的多少来定义一个常用对象和闲置对象,不过没人这么蛋疼。。。

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

推荐阅读更多精彩内容