首先讲一讲执行环境:

  执行环境按照字面上来理解就是指目前代码执行所在的环境。

当JavaScript代码执行的时候,会进入不同的执行上下文,这些执行上下文会构成了一个执行上下文栈(Execution context stack,ECS)。

执行环境的分类

  •   全局执行环境:

    在浏览器中,其指window对象,是JS代码开始运行时的默认环境。
    全局执行环境的变量对象始终都是作用域链中的最后一个对象。

  •   函数执行环境:

    当某个函数被调用时,会先创建一个执行环境及相应的作用域链。然后使用arguments和其他命名参数的值来初始化执行环境的变量对象。当该函数执行完之后会将该函数的执行环境弹出栈。

  注:上述分类解释也表明了js中只有两种作用域,即全局作用域和函数局部作用域,不存在块作用域。

执行环境的组成

  一个执行环境包括变量对象,内部[[Scope]]属性,this指针这三个属性

  

  (注意:图片来源于简书——理解js的执行环境)

  • 变量对象(Variable object,VO): 变量对象即包含变量的对象,使用包含的变量来初始化变量对象,除了我们无法访问它外,和普通对象没什么区别(全局执行环境的变量对象就是window,我们可以访问window)。
  • [[Scope]]属性:作用域即变量对象,作用域链是一个由变量对象组成的带头结点的单向链表,其主要作用就是用来进行变量查找。而[[Scope]]属性是一个指向这个链表头节点的指针。
  • this: 指向一个环境对象,注意是一个对象,而且是一个普通对象,而不是一个执行环境。

完全是小白的可能不太清楚作用域链,然后补充一下作用域链:

  在前面提到过,当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对该执行环境有权访问的所有变量和函数的有序访问

  作用域链包含了执行环境栈中的每个执行环境对应的变量对象

  在访问一个变量时,先在作用域链表上的第一个变量对象上查找。如果没有找到则继续在作用域链上的第二个变量对象上查找。直至搜索到全局执行环境的变量对象即Window对象。

  

  那么再看看闭包的特殊性访问,

  

function returnfunc (propertyName) {
return function (obj) { //-----这行定义并返回了一个闭包,也被称之为一个匿名函数
return obj[propertyName]; //这里用方括号法访问属性,因为属性是变量(returnfunc()函数的参数)
};
} var savefunc = returnfunc("name"); //调用returnfunc()
var result = savefunc({name:"Picasso"});//调用savefunc()
alert(result); //返回字符串“Picasso” 作者:闭家锁
链接:https://www.zhihu.com/question/36393048/answer/71879330
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

(注意:以下图片来源于知乎——理解活动对象和变量对象的区别

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

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

图的白色虚线表示执行程序产生的效果,它可能表示的是返回一个结果、复制某种值、产生一个新物体、建立某种联系等。

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

可以看到,returnfunc函数在返回内部函数之后其执行环境就不存在了,但是其活动对象仍然在内存中,并没有被销毁;按照前面讲过的一句话“作用域链包含了执行环境栈中的每个执行环境对应的变量对象。”来看,当returnfunc的执行环境不存在之后,其所包含的活动对象是应该会被销毁。事实上,直到匿名函数被销毁,returnfunc的活动对象才会被销毁。这是闭包的特殊性,在匿名函数从returnfunc中被返回后,它的作用域链被初始化为包含returnfunc函数的活动对象和全局变量对象,即使returnfunc函数的执行环境被弹出栈,因为匿名函数的作用域链仍然在引用returnfunc函数的活动对象,returnfunc函数的活动对象仍然在内存中,这样匿名函数就可以访问returnfunc函数中定义的所有变量。

以上内容学习自:

  1.知乎——理解活动对象和变量对象的区别

  2.简书——理解js的执行环境

  3.csdn——js的执行环境和作用域

最新文章

  1. Android分享一款漂亮的折叠书架菜单
  2. ECMAScript toString() 方法
  3. .NET下载文件报错System.UnauthorizedAccessException的解决方法
  4. SharePoint 2010 文档管理系列
  5. JS正则实例
  6. 理解Windows中的路由表和默认网关
  7. Linux kernel驱动相关抽象概念及其实现 之“bus,device,driver”
  8. Swing UI - 可收起与开展内容面板实现演示
  9. freemarker 集成 sitemesh 装饰html页面 shiro 标签
  10. SQL基础学习_05_函数、谓词、CASE表达式
  11. 虚拟机设置固定ip可以使shell远程连接到服务器
  12. Scala隐式转换
  13. fastjson转换json字符串key的首字母小写变大写的解决办法
  14. python base64加密文本内容(1)
  15. @JsonInclude注解,RestTemplate传输值为null的属性,利用FastJson将属性中有空值null的对象转化成Json字符串
  16. Storm快速理解
  17. [POJ2625][UVA10288]Coupons
  18. 转:Content-disposition中Attachment和inline的区别
  19. CPU纯软件半虚拟化技术
  20. Linux多进程CS服务器简单测试

热门文章

  1. Hive导入10G数据的测试
  2. hdu3038 How Many Answers Are Wrong 种类并查集
  3. php.ini配置文件位置
  4. 洛谷P2502[HAOI2006]旅行
  5. 洛谷 P4317 花神的数论题 || bzoj3209
  6. 条形码问题 dp+求某个序列在某种排列中的序号的方法
  7. 排序二叉树 HDOJ 5444 Elven Postman
  8. Eclipse安装svn插件的几种方式 -- 转
  9. 万能makefile模板
  10. HDU 1220 B - Cube