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

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

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

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

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

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

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

 1  <script type="text/javascript">
 2         var color = "blue";
 3         function changeColor(){
 4             var anotherColor = "red";
 5             function swapColors(){
 6                 var tempColor = anotherColor;
 7                 anotherColor = color;
 8                 color = tempColor;
 9                 //color, anotherColor, tempColor
10             }
11             //color and anotherColor
12             swapColors();
13         }
14         changeColor();
15         // color
16         alert("Color is now " + color);
17     </script>

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

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

作用域链:

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

二、作用域

2.1延长作用域链

虽然执行环境只有两种——全局作用域和函数作用域,但是还是可以通过某种方式来延长作用域链。因为有些语句可以在作用域链的顶部增加一个临时的变量对象。

有两种情况会发生这种现象:

1、try-catch语句的catch块;创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。

2、with语句;将指定的对象添加到作用域链中。

 1     <script type="text/javascript">
 2         function buildUrl() {
 3             var qs = "?debug=true";
 4             with(location){
 5                 var url = href + qs;
 6             }
 7             return url;
 8         }
 9         var result = buildUrl();
10         alert(result);
11     </script>

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

with语句详解:

 1 function initUI(){
 2    with(document){
 3         var bd = body,
 4         links =  getElementsByTagName("a"),
 5         i = 0,
 6         len = links.length;
 7         while(i<len){
 8               update(links[i++]);
 9         }
10         getElementById("go-btn").onclick = function(){
11               start();
12         };
13         bd.className = "active"
14    }
15 }

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

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

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

 1 function initUI(){
 2         var doc=document
 3         var bd = doc.body,
 4         links =  doc.getElementsByTagName("a"),
 5         i = 0,
 6         len = links.length;
 7         while(i<len){
 8               update(links[i++]);
 9         }
10         doc.getElementById("go-btn").onclick = function(){
11               start();
12         };
13         bd.className = "active"
14
15 }

catch语句详解:

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

1 try{
2 doSomething();
3 }catch(ex){
4       alert(ex.message);
5 //作用域链在此处改变
6  } 

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

1 try{
2 doSomething();
3  }catch(ex){
4 handleError(ex); //委托给处理器方法
5 } 

优化后的代码,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是没有块级作用域的。

时间: 2024-10-03 14:51:35

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

浅谈javascript中执行环境(作用域)与作用域链_javascript技巧

相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行环境分为全局执行环境和局部执行环境,其中局部执行环境我们又可以称之为函数执行环境.那么究竟什么使执行环境呢?通俗的说,执行环境即为代码执行时所处的环境.我们下来看一看如下代码,再进一步分析之. <script><br>var name="zhuzhenwei"; function changeName(){ if (name

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

原文:从头开始学JavaScript (十)--垃圾收集 一.垃圾收集 1.1javascript垃圾收集机制: 自动垃圾收集,执行环境会负责管理代码执行过程中的使用的内存.而在C和C++之类的语言中,开发人员的一项基本任务就是手动跟踪内存的使用情况,这是造成许多问题的一个根源.在编写javascript程序时候,开发人员不用再关心内存使用的问题,所需内存的分配 以及无用的回收完全实现了自动管理. 1.2垃圾收集原理: 找出那些不再继续使用的变量,然后释放其中占用的内存. 垃圾收集器会按照固定的

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

原文:从头开始学JavaScript (十二)--Array类型 一.数组的创建 注:ECMAscript数组的每一项都可以保存任何类型的数据 1.1Array构造函数 var colors = new Array(); 如果预先知道数组要保存的项目数量,也可以给构造函数传递该数量: var colors = new Array(20); 也可以向构造函数传递数组中应该包含的项: var colors = new Array("red", "blue", "

从头开始学JavaScript (五)——操作符(二)

原文:从头开始学JavaScript (五)--操作符(二) 一.乘性操作符 1.乘法:*      乘法操作符的一些特殊规则: 如果操作数都是数值,按照常规的乘法计算,如果乘积超过了ECMAscript数值的表示范围,则返回infinity或者-infinity 如果有一个操作数是NaN,那返回结果就是NaN 如果是infinity与0相乘,返回NaN 如果infinity与非0数相乘,返回infinity或者-infinity infinity与infinity相乘,返回infinity 如

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

原文:从头开始学JavaScript (八)--变量 一.变量分类: 基本类型值:null.undefined.number.string.Boolean: 引用类型值:保存在内存中的对象,如:Object / Array / Function / Date / RegExp / Error / Map / Set - 二.属性 二者的定义方式是类似的:创建一个变量并为其赋值. 2.1基本类型值不能添加删除属性 2.2引用类型的属性可以动态添加删除属性 例如: 1 <script type=&quo

从头开始学JavaScript (六)——语句

原文:从头开始学JavaScript (六)--语句 一.条件分支语句:if 基本格式: if (<表达式1>){    <语句组1>}else if (<表达式2>){    <语句组2>}else{    <语句组3>}  执行流程: 二.循环语句 2.1前测试循环语句:在循环体内的代码被执行之前就对出口条件求值. 2.1.1while语句 基本格式: do {    <语句组>} while (<表达式>)  执行流

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

原文:从头开始学JavaScript (十一)--Object类型 一.object类型 一个object就是一系列属性的集合,一个属性包含一个名字(属性名)和一个值(属性值). object对于在应用程序中存储和传输数据而言,是非常理想的选择 二.创建object 创建object实例有两种方法: 使用new 操作符后跟object构造函数 使用对象初始化器,也就是对象字面量表示法 2.1使用new 操作符后跟object构造函数创建object实例: 1 var person = new O

浅谈JavaScript 执行环境、作用域及垃圾回收_javascript技巧

执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境都有一个与之关联的变量对象. 全局执行环境是最外围的一个执行环境.根据JavaScript实现所在的宿主环境不同,表示执行环境的对象也不一样.在Web浏览器中,全局执行环境被认为是window对象.因此,所有的全局变量和函数都是作为window对象的属性和方法创建的. 变量对象:环境中定义的所有变量和函数都保存在这个对象中. 作用域链:当代码在一个环境中执行时,会创建变量对象的一个作用域链.作用域链的用途是保证对执行环

javascript执行环境及作用域详解_javascript技巧

最近在重读<javascript高级程序设计3>,觉得应该写一些博客记录一下学习的一些知识,不然都忘光啦.今天要总结的是js执行环境和作用域. 首先来说一下执行环境  一.执行环境         书上概念,执行环境定义了变量或者函数有权访问的其他数据,决定了他们各自的行为.每个执行环境都有一个与之关联的变量对象.环境中定义的所有变量和函数都保存在这个对象中.虽然我们在编写代码的时候无法访问这个对象,但解析器在处理数据时会在后台用到它. 执行环境是一个概念,一种机制,它定义了变量或函数是否有权