基于PHP网站开发的管理系统设计与开发,广东手机微信网站制作,福建省建设厅网站首页,家具全屋定制词法环境 词法作用域 词法作用域#xff08;lexcical scope#xff09;。即JavaScript变量的作用域是在定义时决定而不是执行时决定#xff0c;也就是说词法作用域取决于源码。 词法环境 用于定义特定变量和函数标识符在ECMAScript代码的词法嵌套结构上的关联关系#xff0…词法环境 词法作用域 词法作用域lexcical scope。即JavaScript变量的作用域是在定义时决定而不是执行时决定也就是说词法作用域取决于源码。 词法环境 用于定义特定变量和函数标识符在ECMAScript代码的词法嵌套结构上的关联关系 一个词法环境由一个环境记录项和可能为空的外部词法环境引用构成 词法环境 词法环境记录项 外部词法环境外部词法环境是包含内部词法环境的词法环境 外部词法环境可能有多个内部词法环境 环境记录项 声明式环境记录项 || 对象式环境记录项 执行环境 javascript引擎在执行每个函数实例时都会创建一个执行环境execution context 执行环境中包含一个调用对象call object, 调用对象是一个scriptObject结构scriptObject是与函数相关的一套静态系统与函数实例的生命周期保持一致用来保存内部变量表varDecls、内嵌函数表funDecls、父级引用列表upvalue等语法分析结构。 varDecls和funDecls等信息是在语法分析阶段就已经得到并保存在语法树中 函数实例执行时会将这些信息从语法树复制到scriptObject上 Executable Code and Execution contents “执行上下文”可以看做当前代码的运行环境或者作用域。 Types of Executable Code Global Code全局级别的代码 – 这个是默认的代码运行环境一旦代码被载入引擎最先进入的就是这个环境。 Function Code: 函数级别的代码 – 当执行一个函数时运行函数体中的代码。 Eval Code: 在Eval函数内运行的代码在特定的一次对 eval 的调用过程中eval 代码作为该程序的 Global Code 部分。 每当调用执行一个函数时引擎就会自动新建出一个函数上下文, 函数中函数也可能调用另一个函数这样又创建一个执行环境 也被称为上下文堆栈 执行上下文堆栈 ECMAScript的程序执行都可以看做是一个执行上下文堆栈[execution context (EC) stack]。堆栈的顶部就是处于激活状态的上下文 堆栈最底部即为全局执行上下文环境[global execution context] 激活其它上下文的某个上下文被称为 调用者(caller) 。被激活的上下文被称为被调用者(callee) 。被调用者同时也可能是调用者(比如一个在全局上下文中被调用的函数调用某些自身的内部方法)。 当一个caller激活了一个callee那么这个caller就会暂停它自身的执行然后将控制权交给这个callee. 于是这个callee被放入堆栈称为进行中的上下文[running/active execution context]. 当这个callee的上下文结束之后会把控制权再次交给它的caller然后caller会在刚才暂停的地方继续执行。在这个caller结束之后会继续触发其他的上下文。一个callee可以用返回return或者抛出异常exception来结束自身的上下文。 执行上下文的建立过程 每当调用一个函数时一个新的执行上下文就会被创建出来。然而在javascript引擎内部这个上下文的创建过程具体分为两个阶段: 建立阶段(发生在当调用一个函数时但是在执行函数体内的具体代码以前) 建立变量函数arguments对象参数建立作用域链确定this的值 代码执行阶段: 变量赋值函数引用执行其它代码实际上可以把执行上下文看做一个对象其下包含了以上3个属性 executionContextObj {variableObject: { /* 函数中的arguments对象, 参数, 内部的变量以及函数声明 */ },scopeChain: { /* variableObject 以及所有父执行上下文中的variableObject */ },this: {}} 变量对象(variable object) 变量对象(缩写为VO)是一个与执行上下文相关的特殊对象它存储着在上下文中声明的以下内容 变量 (var, 变量声明)函数声明 (FunctionDeclaration, 缩写为FD);函数的形参 注 只有全局上下文的变量对象允许通过VO的属性名称来间接访问不同执行上下文中的变量对象 对于所有类型的执行上下文来说变量对象的一些操作(如变量初始化)和行为都是共通的。从这个角度来看把变量对象作为抽象的基本事物来理解更为容易。同样在函数上下文中也定义和变量对象相关的额外内容。 抽象变量对象VO (变量初始化过程的一般行为) 全局上下文变量对象GlobalContextVO (VO this global), VO: 所有函数声明(FunctionDeclaration, FD)所有变量声明(var, VariableDeclaration) 函数上下文变量对象FunctionContextVO (VO AO, 并且添加了arguments和形参), AO: 普通参数(formal parameters) 与特殊参数(arguments)对象所有函数声明(FunctionDeclaration, FD)所有变量声明(var, VariableDeclaration) eval上下文 eval会使用全局变量对象或调用者的变量对象(eval的调用来源)变量声明在顺序上跟在函数声明和形式参数声明之后但不会干扰AO中已经存在的同名函数声明或形式参数声明(function x() {}); 类似这样的函数表达式并不会影响AO不管是使用var关键字(在全局上下文)还是不使用var关键字(在任何地方)都可以声明一个变量”。 请记住这是错误的概念 任何时候变量只能通过使用var关键字才能声明。变量的特性 变量有一个特性(attribute){DontDelete},这个特性的含义就是不能用delete操作符直接删除变量属性eval上下文变量没有{DontDelete}特性, 使用一些调试工具(例如Firebug)的控制台测试该实例时请注意Firebug同样是使用eval来执行控制台里你的代码。因此变量属性同样没有{DontDelete}特性可以被删除。作用域 javascript变量的作用域是在定义时决定而不是执行时决定也就是说词法作用域取决于源码编译器通过静态分析就能确定因此词法作用域也叫做静态作用域static scope。但需要注意with和eval的语义无法仅通过静态技术实现所以只能说javascript的作用域机制非常接近词法作用域lexical scope 作用域链 在ECMAScript中会用到内部函数[inner functions]在这些内部函数中我们可能会引用它的父函数变量或者全局的变量。我们把这些变量对象成为上下文作用域对象[scope object of the context]. 类似于上面讨论的原型链[prototype chain]我们在这里称为作用域链[scope chain] 作用域链与一个执行上下文相关, 用于在标识符解析中变量查找。 标示符[Identifiers]可以理解为变量名称、函数声明和普通参数 函数上下文的作用域链在函数调用时创建的包含活动对象和这个函数内部的[[scope]]属性。其scope定义如下Scope AO [[Scope]] 函数在被创建时保存外部作用域是因为这个 被保存的作用域链(saved scope chain) 将会在未来的函数调用中用于变量查找。这种形式的作用域称为静态作用域[static/lexical scope] 在上下文中示意如下 activeExecutionContext {VO: {...}, // or AOthis: thisValue,Scope: [ // Scope chain// 所有变量对象的列表// for identifiers lookup]
};var x 10;function foo() {alert(x);
}(function () {var x 20;foo(); // 10, but not 20
})();在标识符解析过程中使用函数创建时定义的词法作用域变量解析为10而不是20。此外这个例子也清晰的表明一个函数这个例子中为从函数“foo”返回的匿名函数的[[scope]]持续存在即使是在函数创建的作用域已经完成之后。 补充说明 通过构造函数创建的函数的[[scope]]属性总是唯一的全局对象 在代码执行阶段有两个声明能修改作用域链。这就是with声明和catch语句 在代码执行过程中如果使用with或者catch语句就会改变作用域链。而这些对象都是一些简单对象他们也会有原型链。这样的话作用域链会从两个维度来搜寻。 在解释执行阶段 遇到变量需要解析时会首先从当前执行环境的活动对象中查找 如果没有找到而且该执行环境拥有者有prototype属性时 则会从prototype链中查找 否则将会按照作用域链查找 end!转载于:https://www.cnblogs.com/mininice/p/3876307.html