Javascript Closures (2)
作者:Dreamer 来源:Dreamer’s Blog 发布时间:2009-03-18 12:22:00
在上一篇文章中,简单介绍了下闭包(closure)和原型链,现在继续来研究闭包的内部机制。
对了,所有的东西都参考自这篇文章:Javascript Closures
执行环境(Execution Context)
执行环境(Execution Context) 是 ECMAScript 定义中的一个抽象概念,用来定义 ECMAScript 执行时所需要的一些行为。所有的 JS 代码都是在一个执行环境中被执行的,全局的代码是在一个全局的执行环境中执行的,而对函数的每次调用都会产生一个相应的执行环境。
当一个函数被调用的时候,就会进入到一个执行环境中,当另外一个函数被调用(或者同一个函数被递归调用)的时候就会进入到一个新的执行环境,而且当这个函数返回的时候,就会回到原来的执行环境中。所以,运行中的 JS 代码会有一个执行环境堆栈。
当一个执行环境被创建的时候,会发生一系列的事情。首先,它会创建一个 “Activation” 对象,不过这个对象很特别,因为它没有 prototype 并且不能在代码中直接引用。然后就会创建一个叫做 “arguments” 类似数组的对象,里面保存了传过来的参数,同时”Activation” 对象上会创建一个叫做 “arguments” 的属性并指向刚刚创建的 “arguments”对象。
接下来,执行环境就会被赋予一个作用域(scope)。一个作用域一般是由一系列的对象组成的,每个函数对象都有一个内部的 [[scope]] 属性,该属性也是由一系列的对象组成的。执行环境被赋予的那个 scope 就会被相应函数对象中的[[scope]] 属性所引用,同时会把开始创建的 “Activation” 对象插入到 scope 包含对象的最前面。
然后,就会使用ECMA 262提到的一个 “Variable” 对象进行变量初始化。事实上,前面创建的 “Activation” 对象和这里的”Variable” 对象其实是同一个对象。初始化的时候会在 “Variable” 对象上创建一些和函数定义中的参数同名的属性,如果有传过来的参数,就会把传过来的值赋给 “Variable” 对象上相应的属性(不然就赋值undefined)。如果有内部函数,那么就会创建一个函数对象,然后在 “Variable” 对象上创建一个和内部函数名字相同的属性,并把刚创建的函数对象赋值给它。变量初始化的最后一步就是在 “Variable” 对象上创建和函数内部的声明的本地变量同名的所有属性。
其实在变量初始化的时候,所有本地变量对应的 “Variable” 对象上的属性值都是 undefined,它们并没有被真正初始化。只有当执行到函数体内对它们赋值的语句的时候,它们才算是真正初始化了。
正是由于 “Activation” 对象和 “Variable” 对象其实是同一个对象,所以在代码中,”Activation” 对象上的 “arguments” 属性就可以像本地变量那样被引用。
最后,会对this关键字赋一个值。如果this被赋值为一个对象,那么以this.为前缀的所有属性都是指该对象上的属性,如果this 被赋值为 null ,那么它就指向 global 对象。
全局的执行环境相对于函数的执行环境来说,有那么一点不同。因为全局执行环境不需要参数,所以它也就不需要创建一个 “Activation” 对象来引用它们。全局执行环境也有一个 scope,不过它的 scope只包含一个对象,就是 global对象。它也会经过变量初始化,而且 global 对象会充当其中的 “Variable” 对象 ,这就是为什么在全局作用域声明的函数和变量都会作为 global 对象的属性。全局的执行环境中,this关键字指向的也是 global 对象。
![](https://www.aspxhome.com/images/zang.png)
![](https://www.aspxhome.com/images/jiucuo.png)
猜你喜欢
- 首先第一步,打开文件,有两个函数可供选择:open() 和 file()①. f = open('file.txt
- 在程序中,经常需要将⼀组(通常是同为某个类型的)数据元素作为整体 管理和使⽤,需要创建这种元素组,⽤变量记录它们,传进传出函数等。 ⼀组数据
- 进程、线程和协程之间的关系和区别也困扰我一阵子了,最近有一些心得,写一下。进程拥有自己独立的堆和栈,既不共享堆,亦不共享栈,进程由操作系统调
- 本文介绍了数据库索引,及其优、缺点。针对MySQL索引的特点、应用进行了详细的描述。分析了如何避免MySQL无法使用,如何使用EXPLAIN
- 一、安装并配置 JMeter下载官网下载,下载二进制的这个 zip配置环境变量然后解压到你喜欢的位置,配置环境变量,新建一个 JMETER_
- 一、安装MySQL下载MySQL的社区版的压缩包:https://dev.mysql.com/get/Downloads/MySQL-8.0
- 一、利用Google API生成二维码Google提供了较为完善的二维码生成接口,调用API接口很简单,以下是调用代码:$urlToEnco
- 前言在深度学习训练的过程中,随着网络层数的提升,我们训练的次数,参数都会提高,训练时间相应就会增加,我们今天来了解迁移学习一、经典的卷积神经
- 布尔表示两值之一:True 或 False。 布尔值在编程中,通常需要知道表达式是 True 还是 False。可以计算 Python 中的
- 背景一直以来,中式占卜都是基于算命先生手工实现,程序繁琐(往往需要沐浴、计算天时、静心等等流程)。准备工作复杂(通常需要铜钱等道具),计算方
- sql查询数组中是否包含某个内容find_in_set如果表Atable中的a字段内容是1,2,3 的格式(a字段是用,分隔的),要查询该字
- 本文为大家讲解了pytorch实现CNN卷积神经网络,供大家参考,具体内容如下我对卷积神经网络的一些认识卷积神经网络是时下最为流行的一种深度
- 以下内容给大家介绍了MYSQL通过Adjacency List (邻接表)来存储树形结构的过程介绍和解决办法,并把存储后的图例做了分析。今天
- 小程序miniso的一个发布内容截图功能,话不多,先上代码wxml文件:<view class="cut-1-1 t-c {
- 列表的索引取值1. 列表的索引和字符串一样,列表中的每一个元素也都有一个属于自己的编号,这个编号就是列表的索引。2. 列表索引取值通过字符串
- 运行环境:Windows 8.1Python:2.7.6在安装的时候,我使用的pip来进行安装,命令如下:pip install beaut
- 概述TensorFlow2 的基本操作和 Numpy 的操作很像. 今天带大家来看一看 TensorFlow 的基本数据操作.创建数据详细讲
- 本文实例讲述了python创建临时文件夹的方法。分享给大家供大家参考。具体实现方法如下:import tempfile, os tempfd
- 1、PIL介绍以及图片分割Python 3 安装: pip3 install Pillow1.1 image 模块Image模块
- 与部门同事做了个小小的交流,话题杂而浅,在此做一个小纪录。1、什么是设计工业设计、环境设计、建筑设计、平面设计、网页设计、服装设计、信息设计