作为小白入坑的这段时间,这三个概念很早便深入我心,但是却总感觉模模糊糊不知道该怎么讲清楚其中的关系,甚至有时候还会混淆,正好今天拿出来复盘一下。
举三个栗子
执行上下文
简单直白的讲执行上下文就是一种环境。
类比一个卖猪肉的宇宙人小明,小明今天想要卖猪肉,那么首先宇宙是最根本的环境,在宇宙茫茫星海中他选择了在地球上卖,所以他来到了地球,在地球这么多的地方选择了中国某县的猪肉铺。至此他就开始卖猪肉了。你想想看,很大的空间里,小明先把宇宙压入栈底,而后把存在与其中的地球又压入栈内,然后又把地球中的中国某县压入栈内部。是不是很像执行环境的压栈操作?当他在某县赚够了码农的钱后被宇宙警察发现非法卖肉,便准备溜了,先从某县走出,然后逃离地球,最后跑出宇宙。
(出入栈操作)
在每个执行上下文环境中都会提供一些变量。这是不是很像每个环境独有的物质基础?比如在地球这个执行上下文环境中还有其他一些地方可供选择,在某县卖肉的时候你需要的砍刀不就是这个环境提供给你的变量?
回顾一下:每个执行上下文是一种环境,这种环境有大有小(大小指的是内部包含的变量多少)在调用某个函数时就将这个函数的执行上下文压入栈中,同时执行上下文中的变量对象被激活可用变为活动变量。函数调用完毕就把此函数的执行上下文出栈,当然连同这个环境中的变量对象一起被踢出局,同时激活当前栈顶的执行上下文的变量对象。
作用域链
作用域链就是一种寻找变量的链条关系,每个执行上下文中包含本环境中的变量对象并创建链条指向他的前一作用域。
接上个例子,小明在某县猪肉铺卖猪肉的时候,为了杀一头猪妖,他必须找到一把锋利的宝刀,但是寻遍了中国某县也没有适合的刀,于是他考虑是去日本打造一把军刀还是在宇宙深处找一找有没有适合的刀?犹豫不决,但是他毕竟是个商人,为了把刀出去大动干戈还花钱,不如就地球内随便找把刀吧,但必须是他要的那个独一无二的类型才能发挥他杀猪的最高境界!于是他在地球某处终于找到了那把绝世宝刀!顺利杀妖抱得美人归。
至此,我们来分析一下:小明杀猪妖就是调用某个函数解决实际需求,但是他需要某个独一无二的宝刀(变量),在中国某县并未找到(当前作用域中并没有定义此变量),于是他不得已在地球范围内寻找(顺着作用域链条在前一作用域中寻找),在地球中找到了!(前一作用域中找到了此变量),于是愉快的杀猪去了(找到了变量顺利解决了实际需求)。
回顾一下:作用域链是由每个作用域链接成的呈链状变量对象集合,当前作用域不存在的变量就会依次向前一作用域寻找,直到在根作用域在寻找,并且只能按照一定的顺序寻找,不能够逆着顺序寻找。
原型链
原型链就是一种对象和创建此对象的对象之间的呈链式的关系链条。
还是上个例子吧,小明觉得卖猪肉太不赚钱,于是搞起了养殖业,他从某猪户中购得一怀了崽的猪,过了几天便下崽了,于是就变成了猪生猪代代相传。这个小明发现每一代猪都是俩并且这俩猪还只和他猪爸猪妈交流。
到这大家可以分析一下:这第一代怀了崽的猪就是null,后期由null产生了object与object.prototype这两个对象,再由这两个对象派生出了其他对象。或许一张图你会看得更明白。
回顾一下:原型链其实就是对象和自己父母的关系,父母在和爷奶的关系。每代之间会有特点添加进去,在你这里需要调用某个方法你却没有时,可以向上一直找寻找到后调用。
分析关系
红宝书中讲:由多个执行上下文的变量对象构成的链表就叫做作用域链,所以作用域链表的产生是依附于执行上下文的变量对象的,根据每个执行上下文有自己的作用域,而后根据压栈的关系组合成作用域链表。
原型链和他俩不掺合,原型链其实在构造对象的过程中就已经产生了,除非手动的修改他的原型,这也是我们平时在调用一些自带的API,并没有写具体实现却能正常跑下来的原因。
试想一下:现在写了一个函数,并没有调用这个函数,那么现在有执行上下文吗?现在有作用域吗?现在有作用域链吗?现在有原型链吗?
执行上下文没有,执行上下文是调用时产生的。作用域已经存在了,书写完一个函数就确定了函数自己的作用域。那么作用域链呢?当然是执行上下文压栈是才存在的。原型链也是函数写完时他就已经存在了,和是否调用该函数并无关系。
感谢各位看官至此,希望批评指正。
参考资料:
(图片来源于网络)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。