[转自:http://www.cnblogs.com/fool/archive/2010/10/19/1855266.html]
示例:
var outerVar1="variable in global code";
function fn1(arg1, arg2){
var innerVar1="variable in function code";
function fn2() {
return outerVar1+" - "+innerVar1+" - "+" - "+(arg1 + arg2);
}
return fn2();
}
var outerVar2=fn1(10, 20);
执行处理过程大致如下:
1. 初始化Global Object即window对象,Variable Object为window对象本身。创建Scope Chain对象,假设为scope_1,其中只包含window对象。
2. 扫描JS源代码(读入源代码、可能有词法语法分析过程),从结果中可以得到定义的变量名、函数对象。按照扫描顺序:
2.1 发现变量outerVar1,在window对象上添加outerVar1属性,值为undefined;
2.2 发现函数fn1的定义,使用这个定义创建函数对象,传给创建过程的Scope Chain为scope_1。将结果添加到window的属性中,名字为fn1,值为返回的函数对象。注意fn1的内部[[Scope]]就是 scope_1。另外注意,创建过程并不会对函数体中的JS代码做特殊处理,可以理解为只是将函数体JS代码的扫描结果保存在函数对象的内部属性上,在函数执行时再做进一步处理。这对理解Function Code,尤其是嵌套函数定义中的Variable Instantiation很关键;
2.3 发现变量outerVar2,在window对象上添加outerVar2属性,值为undefined;
3. 执行outerVar1赋值语句,赋值为"variable in global code"。
4. 执行函数fn1,得到返回值:
4.1 创建Activation Object,假设为activation_1;创建一个新的Scope Chain,假设为scope_2,scope_2中第一个对象为activation_1,第二个对象为window对象(取自fn1的 [[Scope]],即scope_1中的内容);
4.2 处理参数列表。在activation_1上设置属性arg1、arg2,值分别为10、20。创建arguments对象并进行设置,将arguments设置为activation_1的属性;
4.3 对fn1的函数体执行类似步骤2的处理过程:
4.3.1 发现变量innerVar1,在activation_1对象上添加innerVar1属性,值为undefine;
4.3.2 发现函数fn2的定义,使用这个定义创建函数对象,传给创建过程的Scope Chain为scope_2(函数fn1的Scope Chain为当前执行上下文的内容)。将结果添加到activation_1的属性中,名字为fn2,值为返回的函数对象。注意fn2的内部 [[Scope]]就是scope_2;
4.4 执行innerVar1赋值语句,赋值为"variable in function code"。
4.5 执行fn2:
4.5.1 创建Activation Object,假设为activation_2;创建一个新的Scope Chain,假设为scope_3,scope_3中第一个对象为activation_2,接下来的对象依次为activation_1、window 对象(取自fn2的[[Scope]],即scope_2);
4.5.2 处理参数列表。因为fn2没有参数,所以只用创建arguments对象并设置为activation_2的属性。
4.5.3 对fn2的函数体执行类似步骤2的处理过程,没有发现变量定义和函数声明。
4.5.4 执行函数体。对任何一个变量引用,从scope_3上进行搜索,这个示例中,outerVar1将在window上找到;innerVar1、arg1、arg2将在activation_1上找到。
4.5.5 丢弃scope_3、activation_2(指它们可以被垃圾回收了)。
4.5.6 返回fn2的返回值。
4.6 丢弃activation_1、scope_2。
4.7 返回结果。
5. 将结果赋值给outerVar2。
分享到:
相关推荐
如果又调用了另外一个函数(或者递归地调用同一个函数),则又会创建一个新的执行环境,并且在函数调用期间执行过程都处于该环境中。当调用的函数返回后,执行过程会返回原始执行环境。因而,运行中的 JavaScript ...
为了解决这个问题,开发者会利用Node.js环境中的JavaScript执行环境,因为它允许在服务器端运行JavaScript代码。 GPT-4(Generative Pre-trained Transformer 4)是一个假设性的后续版本的OpenAI的大规模语言模型。...
- **异步处理**:如果解析过程可能导致阻塞,可以考虑使用Web Worker或其他异步策略,让解析在后台线程中执行。 - **缓存策略**:对于经常重复解析的Markdown文本,可以考虑使用缓存机制,避免重复计算。 在实际...
4. **事件监听**:Vue.Draggable提供了丰富的事件,如`start`、`end`、`sort`、`add`、`remove`等,允许开发者在拖放过程中执行特定的操作。 5. **动画效果**:Vue.Draggable可以设置动画效果,使拖放操作看起来更...
以上是对“JavaScript函数式编程”可能包含的知识点的一个大致介绍。考虑到文档中提供的信息有限,这些知识点基于通用的JavaScript函数式编程概念。如果要详细学习和应用这些概念,需要查看具体的教材或者文档来获取...
首先,JavaScript是前端开发的核心语言之一,它允许在用户浏览器端执行代码,实现动态交互效果。在创建JavaScript版的俄罗斯方块时,我们需要掌握以下几个关键点: 1. **事件处理**:游戏中的每一动作,如移动、...
根据提供的文件信息,我们可以推断出此文档与《JavaScript忍者秘籍》这本书有关,主要...以上是对《JavaScript忍者秘籍》这本书知识点的一个大致总结,希望能够帮助到正在学习JavaScript或想要进一步提升技能的读者们。
在实际应用中,使用sql.js的步骤大致如下: 1. 引入库:首先,你需要在HTML文件中引入sql.js的库文件,这通常是一个`.wasm`文件和一个`.js`文件,它们提供了与SQLite交互的API。 2. 加载数据库:接着,通过...
首先,JavaScript中的BUG可以大致分为两类:一类是由于程序逻辑设计(即编程思想)混乱导致的错误;另一类是在将设计思想转化为代码的过程中引入的错误。逻辑设计错误往往难以诊断和修复,因为它们可能涉及到程序的...
2. **运行时错误**则是在代码执行过程中发生的错误,例如访问未定义的变量、类型不匹配等。 这些错误不仅会导致脚本停止执行,还可能使整个页面变得不可用。为了避免这种情况,JavaScript提供了几种处理错误的方法...
JavaScript单元测试是软件开发过程中的一个关键环节,它允许开发者对代码的各个独立部分进行验证,确保它们在预期情况下能够正确工作。JSUnit是专为JavaScript设计的一个单元测试框架,它使得JavaScript应用程序的...
JavaScript Packer 2 的工作流程大致分为以下几步: 1. **预处理**:删除不必要的空格、换行和注释,这是最基本的压缩步骤。 2. **变量名缩写**:使用字母表中的字符替换原有的变量名,例如,将长变量名"variable...
4. JS Engine:执行JavaScript代码的引擎,需要考虑性能和功耗,可能需要实现轻量级或者高效的执行策略。 浏览器的工作流程大致如下:首先,DOM Builder解析HTML文档生成DOM树;接着,JS DOM Binding创建JavaScript...
实现过程大致如下: 1. 当页面加载时,JavaScript代码(如`Dmenu1.0_b.js`)会被执行。 2. 使用Ajax(异步JavaScript和XML)技术,JavaScript向服务器发送请求,请求菜单数据。 3. 服务器响应,将`menuitem.txt`和`...
1. 执行全局脚本(Script):这是整个执行过程的起点,全局脚本中的同步代码会进入执行栈。 2. 执行宏任务:执行栈为空后,EventLoop会从任务队列中取出一个宏任务进行执行。宏任务执行完毕后,会检查当前是否有微...
这个过程称为“编译”或“转译”,因为`.wat`文件首先会被解析,然后转换成JavaScript语法,最终生成一个可直接在JavaScript环境中运行的模块。 在JavaScript开发中,`wast2js`扮演了重要角色,尤其是在处理需要高...
使用`Draco`解码器的过程大致分为以下几个步骤: 1. 加载`Draco`解码器资源:确保`draco_decoder.js`和`draco_decoder.wasm`已成功加载。通常,这可以通过异步加载来实现,例如使用`fetch`或`XMLHttpRequest`请求...
这个过程可以大致分为以下几个关键阶段: 1. 用户请求:当用户在浏览器中键入URL并按下回车时,这个请求会被发送到指定的服务器。请求通常包含HTTP(超文本传输协议)或HTTPS(安全套接字层超文本传输协议),用于...
QUnit 提供了一种结构化的方式来编写和执行单元测试,确保代码的正确性,避免在开发过程中引入错误。 ### QUnit 的基本结构 QUnit 的测试通常包含在一个 HTML 文件中,该文件引用 QUnit 的库以及要测试的 ...
JavaScript中的错误大致可以分为三类: - **语法错误**:这类错误是由不正确的语法引起的,通常在编译时就能被检测出来。 - **运行时错误**:这类错误发生在程序运行的过程中,常见的例子包括类型错误、引用错误等。...