原文:从头开始学JavaScript (九)——执行环境和作用域

一、执行环境:定义了变量或者函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有与之关联的变量对象。

变量对象:保存着环境中定义的变量和函数。

作用域链:保证对执行环境有权访问的所有变量和函数的有序访问。

标识符解析:沿着作用域链一级一级地搜索标识符的过程。

通过例子来说明执行环境、变量对象以及作用域链:

  <script type="text/javascript">
var color = "blue";
function changeColor(){
var anotherColor = "red";
function swapColors(){
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
//color, anotherColor, tempColor
}
//color and anotherColor
swapColors();
}
changeColor();
// color
alert("Color is now " + color);
</script>

上述例子中的执行环境、执行流程:

画的不好,请各位看官见谅。。。。。。。

作用域链:

执行环境就像一个盒子,全局环境是最外面的盒子,里面包含着很多函数的盒子,每个函数的盒子里面又包含着它自己的子函数盒子,打开的时候是从外而内依次线性打开的,如果只打开了全局环境的盒子,那么只能看到全局环境里那些盒子以外的东西,比如全局盒子有两个子盒子(第一个盒子里面有饼干,第二个盒子里面有蛋糕)和一个小玩具,那么你只能拿到玩具,但是拿不到饼干和蛋糕。如果再继续打开了全局盒子的第一个子盒子,那么既能拿到全局变量里的玩具又能拿到饼干,但是没办法拿到蛋糕。

二、作用域

2.1延长作用域链

虽然执行环境只有两种——全局作用域和函数作用域,但是还是可以通过某种方式来延长作用域链。因为有些语句可以在作用域链的顶部增加一个临时的变量对象。
有两种情况会发生这种现象:
1、try-catch语句的catch块;创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
2、with语句;将指定的对象添加到作用域链中。
     <script type="text/javascript">
function buildUrl() {
var qs = "?debug=true";
with(location){
var url = href + qs;
}
return url;
}
var result = buildUrl();
alert(result);
</script>

with会把location对象的所有属性和方法包含到变量对象中,并加入到作用域链的顶部。此时访问href实际上就是location.href。

with语句详解:

 function initUI(){
with(document){
var bd = body,
links = getElementsByTagName("a"),
i = 0,
len = links.length;
while(i<len){
update(links[i++]);
}
getElementById("go-btn").onclick = function(){
start();
};
bd.className = "active"
}
}

这里使用with语句来避免多次书写document,看上去更高效,实际上产生了性能问题。

当代码流执行到一个with表达式时,执行环境的作用域链会被临时改变,此时with的变量对象会被创建添加到作用域链的前端,这就意味着此时函数的所有局部变量都被推入到第二个作用域链中的变量对象,因此访问代价更高了。

所以,在程序中应避免使用with语句,在这个例子中,只要简单的把document存储在一个局部变量中就可以提升性能。

 function initUI(){
var doc=document
var bd = doc.body,
links = doc.getElementsByTagName("a"),
i = 0,
len = links.length;
while(i<len){
update(links[i++]);
}
doc.getElementById("go-btn").onclick = function(){
start();
};
bd.className = "active" }

catch语句详解:

当try代码块中发生错误时,执行过程会跳转到catch语句,然后把异常对象推入一个可变对象并置于作用域的头部。在catch代码块内部,函数的所有局部变量将会被放在第二个作用域链对象中。

 try{
doSomething();
}catch(ex){
alert(ex.message);
//作用域链在此处改变
}

请注意,一旦catch语句执行完毕,作用域链机会返回到之前的状态。try-catch语句在代码调试和异常处理中非常有用,因此不建议完全避免。你可以通过优化代码来减少catch语句对性能的影响。一个很好的模式是将错误委托给一个函数处理,例如:

 try{
doSomething();
}catch(ex){
handleError(ex); //委托给处理器方法
}

优化后的代码,handleError方法是catch子句中唯一执行的代码。该函数接收异常对象作为参数,这样你可以更加灵活和统一的处理错误。由于只执行一条语句,且没有局部变量的访问,作用域链的临时改变就不会影响代码性能了。

2.2没有块级作用域

Javscript没有块级作用域。看下面代码:

if(true){
var myvar = "jack";
}
alert(myvar);// jack

根据上面我们讨论的,如果有块级作用域,外部是访问不到myvar的。再看下面

for (var i=0;i<5;i++){
console.log(i)
} alert(i); // 5

对于有块级作用域的语言来说,i做为for初始化的变量,在for之外是访问不到的,这允分证明了,javascript是没有块级作用域的。

从头开始学JavaScript (九)——执行环境和作用域的更多相关文章

  1. 深入理解javascript中执行环境(作用域)与作用域链

    深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...

  2. Javascript手记-执行环境和作用域

    执行环境是javascript一个重要的概念,执行环境定义了变量有权访问其他数据决定了他们各自的行为,每个执行环境 都有一个与之关联的变量,环境中定义的所有变量和函数都保存在这个对象中,虽然我们编写的 ...

  3. JavaScript之执行环境及作用域

        执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中.我们编写的代码是无法访问这个对象的,但解 ...

  4. javascript中执行环境和作用域(js高程)

    执行环境(execution context,为简单起见,有时也成为“环境”)是javascript中最为重要的一个概念.执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境 ...

  5. 从头开始学JavaScript (十)——垃圾收集

    原文:从头开始学JavaScript (十)--垃圾收集 一.垃圾收集 1.1javascript垃圾收集机制: 自动垃圾收集,执行环境会负责管理代码执行过程中的使用的内存.而在C和C++之类的语言中 ...

  6. JavaScript之一: 闭包、执行环境、作用域链

    这是大虾的第一篇博文,大虾试图用最直白的语言去描述出所理解的东西,大虾是菜鸟,水平有限,有误的地方希望路过的朋友们务必指正,谢谢大家了. 从读书时代一路走来,大虾在学习的时候逐渐喜欢上了去追寻根源,这 ...

  7. 从头开始学JavaScript (十一)——Object类型

    原文:从头开始学JavaScript (十一)--Object类型 一.object类型 一个object就是一系列属性的集合,一个属性包含一个名字(属性名)和一个值(属性值). object对于在应 ...

  8. 从头开始学JavaScript (十二)——Array类型

    原文:从头开始学JavaScript (十二)--Array类型 一.数组的创建 注:ECMAscript数组的每一项都可以保存任何类型的数据 1.1Array构造函数 var colors = ne ...

  9. 从头开始学JavaScript (八)——变量

    原文:从头开始学JavaScript (八)--变量 一.变量分类: 基本类型值:null.undefined.number.string.Boolean: 引用类型值:保存在内存中的对象,如:Obj ...

随机推荐

  1. web项目启动,运行方法

    1.显示器(Listener) web文件加入 <listener>      <listener-class>cn.ro.common.InitListener</li ...

  2. android关键知识

    1.handler 与Looper 与MessageQueue .Message关系 handler:是处理主线程(ui线程)处理耗时操作的线程,通过post message到MessageQueue ...

  3. 【iOS】UIViewController生命周期

    UIViewController有2周期: 在UIViewController中,View存在两个循环:载入循环和卸载循环. 载入循环 1>程序请求controller的view. 2>假 ...

  4. 如何从Terminal Command Line编译并运行Scope

    Ubuntu SDK我们大部分的开发者是非常有效的.它甚至可以帮助我们进行在线调试.在这篇文章中,我们介绍了如何使用command line编译和执行我们scope. 1)创建一个主Scope 我们能 ...

  5. 使用AppCompat_v7 21.0.0d的几个兼容问题

    1.实现新的ActionBarDrawerToggle动画 ActionBarDrawerToggle使用最新的AppCompat_v7 21会出现一个非常帅的动画.使用方式在Androidstudi ...

  6. Java Web整合开发(20) -- Hibernate入门

    Spring与Hibernate整合

  7. Linux下一个CD翻录 创CUE 压缩flac攻略

    于Windows我们通常使用较低EAC翻录压缩发生器CUE找工作的步骤,但在Linux在稍微有点麻烦.每一步,我们需要自己做.经过我的反复尝试寻找和总结了相当不错的方法,使用软件和步骤如下面的. 使用 ...

  8. ashx一般处理程序和HttpHandler

    asp.net项目中,使用.ashx的文件(一般处理程序)可以用于处理客户端发送来的请求,并将服务器端的处理结果返回给客户端.它能返回的类型可以是文本.或者图片.有时候,我们可以在项目中使用.cs的文 ...

  9. Android:抄QQ照片选择器(按相册类别显示,加入选择题)

    这个例子的目的是为了实现类似至QQ照片选择功能.选择照片后,,使用类似新浪微博 微博 页面上显示. 先上效果图:     本例中使用的主要技术: 1.使用ContentProvider读取SD卡全部图 ...

  10. 《Linux Device Drivers》第十四章 Linux 设备型号

    基本介绍 2.6内核设备模型来提供的抽象叙述性描述的一般系统的结构,为了支持各种不同的任务 电源管理和系统关机 用户空间与通信 热插拔设备 设备类型 kobject.kset和子系统 kobject是 ...