原文:从头开始学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. Oracle生成查询包括对应于所有数据表记录语句中指定的字段名

    应用:已知的字段名,表中的所有数据的查询数据库中包含的所有数据表的字段名 操作方法:指定字段名,用户数据库表,它可以执行以下查询 --Oracle生成查询包括对应于所有数据表记录语句中指定的字段名 d ...

  2. 【转】window.scroll 浏览器滚动条的参数总结

    如内容超出单元格,则隐藏style="TABLE-LAYOUT: fixed" 让弹出窗口总是在最上面: <body onblur="this.focus();&q ...

  3. Linux进程管理(-)

    一.进程的类型 能够将执行在Linux系统中的进程分为三种不同的类型: 交互进程:由一个Shell启动的进程.交互进程既能够在前台执行,也能够在后台   执行. 批处理进程:不与特定的终端相关联,提交 ...

  4. Android笔记 之 旋转木马的音乐效果

    一.前言-- 大家一定在百度音乐上在线听过歌,有没有注意到那个旋转唱片-- 就上面那个,当音乐在播放的时候,那个光碟轮子在转,就想旋转木马一般.感觉好好玩啊. 碰巧想起前阵子做音乐播放器,哎,那这个也 ...

  5. Grant的时候报错的解决:Access denied for user &#39;root&#39;@&#39;localhost&#39; (using password: YES)

    mysql> grant all on *.* to 'root'@'192.168.1.1' identified by 'password'; ERROR 1045 (28000): Acc ...

  6. bonecp使用数据源

    bonecp.properties jdbc.driverClass=oracle.jdbc.driver.OracleDriver jdbc.jdbcUrl=jdbc:oracle:thin:@19 ...

  7. Canvas的quadraticCurveTo 和 bezierCurveTo 画曲线 方法细说

    详细代码如下: <!doctype html> <html lang="en"> <head> <script src="htt ...

  8. Team Foundation Server 2015使用教程--默认团队成员连接tfs及checkin操作

  9. HDU-4628 Pieces 如压力DP

    鉴于他的字符串,每一个都能够删除回文子串.子可以是不连续,因此,像更好的模拟压力.求删除整个字符串需要的步骤的最小数量. 最大长度为16,因此不能逐行枚举状态.首先预处理出来全部的的回文子串,然后从第 ...

  10. 终结者:具体解释Nginx(一)

            相信非常多人都听过Nginx.这个小巧的东西能够和Apache及IIS相媲美. 那么它有什么作用呢?一句话.它是一个减轻Web应用server(如Tomcat)压力和实现Web应用se ...