看题说话,分析一下以下代码的作用域
var x = 10; function a() { console.log(x); } function b () { var x = 5; a(); } b();
简单分析一下这个程序吧,虽然不敢保证理解完全正确.先简单介绍点概念.
执行上下文
每当控制器到达ECMAScript可执行代码的时候,控制器就进入了一个执行上下文.
执行上下文是个抽象概念,标准中没有从技术实现上定义执行上下文的具体结构和类型.
就是一系列活动的执行上下文从逻辑上形成一个栈(比较抽象).
栈底总是全局上下文,栈顶是当前(活动的)执行上下文.
当在不同的执行上下文间切换(退出而进入新的执行上下文)的时候,栈会被修改(通过压栈或者出栈的形式).
变量对象
执行上下文的数据是以变量对象的属性形式进行存储的.
一个变量对象(简写为VO)是一个和执行上下文相关的特别对象,存储以下内容:
变量(声明的变量,var)
函数声明(简写为FD)
在上下文中,函数声明的形式参数
作用域链
作用域链是一条变量对象的链,它和执行上下文有关,用于在处理标识符的时候进行变量查询.
函数上下文的作用域链在函数调用的时候创建出来,它包含了活跃对象和该函数的内部[[Scope]]属性.
执行上下文变量大致如下:
activeExecutionContext = { VO:{...},//或者AO this:thisValue, Scope:[ //作用域链,所有变量对象的列表,用来查询标识符 ] }
上面Scope可以定义如下:
Scope = AO+[[Scope]]
可以用数组进行表示:
var Scope = [VO1,VO2,...,VOn];//作用域链
函数的创建
在进入上下文阶段,函数声明会存储在变量/活跃对象中(VO/AO)
[[Scope]]是一个包含了所有上层变量对象的分层链,它属于当前函数的上下文,并在函数创建的时候,保存在函数中.
[[Scope]]是在函数创建的时候i保存起来的----静态的(不变的),只有一次并且一直都存在--直到函数销毁. [[Scope]]与Scope(作用域链)是不同的,前者是函数的属性,后者是上下文的属性.拿上面的来说a函数的 [[Scope]]:
a.[[Scope]] = [
globalContext.VO //===Global
]
函数调用后,就会进入函数上下文,此时创建活跃对象并且确定this的值和Scope(作用域链).
函数激活
在进入上下文,AO/VO创建之后,上下文的Scope属性(作用域链)会定义如下所示:
Scope = AO+[[Scope]]
AO会添加在作用域链的最前面
Scope = [AO].concat([[Scope]]);
处理标识符其实就是一个确定变量(或者函数声明)属于作用域中哪个变量对象的过程.
此算法返回的总是一个引用类型的值,其base属性就是对应的变量对象(或者如果变量不存在的时候返回null),其property name属性的名字就是要查询的标识符.
标识符处理过程包括了对应的变量名的属性查询,如:在作用域链中会进行一系列的变量对象的检测,从作用域链的最底层上下文一直到最上层上下文
所以,在查询过程中上下文中的局部变量相比较上层上下文的变量会优先被查询到
分析如下:
全局上下文的变量对象如下:
globalContext.VO===Global={
x:10,
a:,
b:
}
在"a"函数创建的时候,其[[Scope]]属性如下所示:
a.[[Scope]]=[
globalContext.VO
]
在"b"函数创建的时候,其[[Scope]]属性如下所示:
b.[[Scope]]=[
globalContext.VO
]
在"b"函数激活的时候(进入上下文时),"b"函数上下文的活跃对象如下:
bContext.AO={
x:5
}
同时,"b"函数上下文的作用域如下所示:
bContext.Scope=[bContext.AO,globalContext.VO]
在"a"函数激活的时候(进入上下文时),"a"函数上下文的活跃对象如下:
aContext.AO={
}
同时,"a"函数上下文的作用域如下所示:
aContext.Scope=[aContext.AO,globalContext.VO]
"x"标识符的查找过程:
"x"
----aContext.AO//没有找到
----globalContext.VO //找到 10
相关推荐
本文主要介绍了javascript中执行环境(作用域)与作用域链,并在文章结尾处做出了总结,感兴趣的朋友可以看下
Js中的变量作用域问题: 1、没有块级作用域。Js中的变量作用域不是以{}为界的,不像C/C++/Java。 如: 代码如下: if(true){ var name = “qqyumidi”; } alert(name); // 结果:qqyumidi Js会...
作用域和闭包在JavaScript里非常重要。但是在我最初学习JavaScript的时候,却很难理解。这篇文章会用一些例子帮你理解它们。 我们先从作用域开始。 作用域 JavaScript的作用域限定了你可以访问哪些变量。有两种作用...
在JS中有全局作用域和函数作用域,而在Nodejs中也自己的作用域,分为全局作用域(global)和模块作用域。 js作用域: 以前学js的时候我们的全局对象是window,如: var a = 10; console.log(window.a); 我们定义的...
函数和作用域是JavaScript的重要组成部分,我们在使用JavaScript编写程序的过程中经常要用到这两部分内容,作为初学者,我经常有困惑,借助写此博文来巩固下之前学习的内容。 (一)JavaScript函数 JavaScript函数是...
作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。 活
首先说明一下:Js中的作用域不同于其他语言的作用域,要特别注意
主要介绍了JavaScript中的作用域和闭包问题,是JS入门学习中的基础知识,需要的朋友可以参考下
下面小编就为大家带来一篇浅谈js的解析顺序 作用域 严格模式。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
request 请求对象 类型 javax.servlet.ServletRequest 作用域 Request response 响应对象 类型 javax.servlet.SrvletResponse 作用域 Page pageContext 页面上下文对象 类型 javax.servlet.jsp.PageContext...
优化 JavaScript 性能,使它运行足够快 一个关键因素:运行的时间 管理作用域 操作数据 流控制 Reflow DOM操作 长时间运行的脚本处理
每次调用javascript函数的时候,都会为之创建一个新的对象来保存变量,把这个对象添那个加至作用域中,当函数返回时,就从作用域链中将这个绑定变量的对象删除,如果不存在嵌套函数,也没有其他引用指向这个绑定的...