执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中。我们编写的代码是无法访问这个对象的,但解析器在处理数据时会在后台使用它。
 
    全局执行环境是最外围的一个执行环境,在Web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法来创建的。某个执行环境中的所有代码执行完毕后,该环境就会被销毁,保存在其中的所有变量和函数定义也随之销毁。
 
    每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中,在函数执行后,栈将其环境弹出,将控制权返回给之前的执行环境。ECMAScript程序中的执行流正是由这个方便的机制控制着。
 
    当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数进行的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象,如果这个环境是函数,则将其活动对象作为变量对象。活动变量最开始时只包含一个变量,即arguments对象(这个对象在全局环境中是不存在的)。作用域链中的下一个变量对象来自包含(外部)环境,再下一个变量对象则来自于再下下个包含(外部)环境,这样一直延续到全局执行环境,全局执行环境的变量对象始终都是作用域链中的最后一个对象。
 
    标识符解析是沿着作用域链一级一级向上(外)搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级向后回溯,直至找到标识符为止。(比如:在全局执行环境中定义了一个name属性,当在一个函数中使用了未声明的变量name,这时,js在预编译时,会向上回溯直到找到name属性位置。)
 
    下图中矩形表示特定的环境。其中内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部变量环境中的任何变量和函数。这些环境之间的练习是线性的,有次序的。每个环境变量都可以向上搜索作用域链,以查询变量和函数名;反之则是不行。
    注意,函数参数也被当作变量来对待,因此其访问规则与执行环境中的其他变量相同。

1、延长作用域链

    虽然执行环境的类型总共只有两种——全局和局部(函数)。但还是可以通过其他方法来延长作用域链。因为有些语句在作用域链的前端临时增加了一个变量对象,该变量对象会在代码执行后被移除。当执行流进入下列任一语句时,作用域链就会得到加长:
  • try-catch语句的catch块
  • with语句
    这两个语句都会在作用域链前端增加一个变量对象。对于with语句来说,会将指定的对象添加到作用域链中。对于catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
 

2、没有块级作用域

if(true)
{
var color = "blue";
}
alert(color);
    注意:如果是在C#、java中,color会在if语句执行完毕后被销毁,但在JavaScript中,if语句中的变量声明会将变量添加到当前的执行环境中(在这里是全局执行环境)。在使用for语句时尤其要牢记这一差异,例如
for (var i=0;i<10;i++){
doSonmething(i);
}
alert(i); //10
    对于C#,java语言来说,for语句初始化变量的表达式所定义的变量,最会存在于循环的环境中。而对JavaScript来说,for语句创建的变量i即使for循环结束后,也依旧会存在与循环外部的执行环境中。

在使用var关键字声明变量时,这个变量将被自动添加到最接近的环境中。在函数内部,最接近的环境就是函数的局部环境。在with语句中,最接近的环境是函数环境。所入初始化变量时没用用var声明,该变量会被自动添加到全局环境。

查询标识符(变量等),当在某个环境中为了读取或写入为引入一个标识符时,就必须通过搜索来确定该标志符实际代表什么。搜索过程从作用域链的前端开始,向上逐级查询与给定名字匹配的标识符。如果局部变量中有,搜索停止,如果没有在逐级向上搜,直到全局环境。如果全局环境中也没有找到这个标识符,则意味着该变量没有声明过。

通过下面这个实例,可以理解查询标识符的过程:

var color="blue";
function getColor(){
return color;
}
alert(getColor()); //blue

调用本例中的函数getColor()时会引用变量color。为了确保变量color的值,将开始一个两步走的搜索过程。首先,搜索getColor()的变量对象,查找其中是否包含一个名为color的标识符。在没有找到的情况下,搜索到下一个变量对象(全局环境的变量对象),然后在那里找到了名为color的标识符。因为搜索到了定义这个变量对象,搜索过程也宣告结束。

在这个搜索过程中,如果存在一个局部的变量的定义,则搜索会自动停止,不会再进入外部环境进行搜索。

 变量查询也不是没有代价。很明显,访问局部变量要比访问全局变量快的多,因为不用向上搜索作用域链,但这个差别在将来的优化下会变得可以忽略不计。

原文:https://www.cnblogs.com/zxj159/archive/2013/05/17/3084598.html

JavaScript之执行环境及作用域的更多相关文章

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

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

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

    原文:从头开始学JavaScript (九)--执行环境和作用域 一.执行环境:定义了变量或者函数有权访问的其他数据,决定了它们各自的行为.每个执行环境都有与之关联的变量对象. 变量对象:保存着环境中 ...

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

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

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

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

  5. Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收

    执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链.函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境.全局执行环境 ...

  6. 深入理解javascript作用域系列第五篇——一张图理解执行环境和作用域

    × 目录 [1]图示 [2]概念 [3]说明[4]总结 前面的话 对于执行环境(execution context)和作用域(scope)并不容易区分,甚至很多人认为它们就是一回事,只是高程和犀牛书关 ...

  7. 【原】javascript执行环境及作用域

    最近在重读<javascript高级程序设计3>,觉得应该写一些博客记录一下学习的一些知识,不然都忘光啦.今天要总结的是js执行环境和作用域. 首先来说一下执行环境 一.执行环境 书上概念 ...

  8. Javascript高级程序设计——执行环境与作用域

    Javascript中执行环境是定义了变量或函数有权访问的其他数据,决定了各自的行为,每个执行的环境都有一个与之关联的变量对象,环境中定义的所以变量和函数都保存在这个对象中. 全局执行环境是最外围的一 ...

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

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

随机推荐

  1. Exception in thread “main” java.sql.SQLException: The server time zone value ‘�й���׼ʱ��’ is unrecognized or represents more than one time zone.

    Exception in thread “main” java.sql.SQLException: The server time zone value ‘�й���׼ʱ��’ is unrecogn ...

  2. UNP总结 Chapter 11 名字与地址转换

    本章讲述在名字和数值地址间进行转换的函数:gethostbyname和gethostbyaddr在主机名字与IP地址间进行转换,getservbyname和getservbyport在服务器名字和端口 ...

  3. es6 import 报错

    现在绝大多数的浏览器都不支持ES6,所以使用es6时需要使用bebal把es6转化为es5, 项目目录: demo1:单个js文件的转化 src文件下的 test1.js const aa=" ...

  4. Run-Time Check Failure #3 - The variable 'p' is being used without being initialized.

    Run-Time Check Failure #3 - The variable 'p' is being used without being initialized. 运行时检查失败 变量p没有初 ...

  5. jQuery获取table当前所在行

    $("div tbody tr").click(function() {         var rows = $(this).prevAll().length + 1;//行号  ...

  6. ASP.NET中在后台用C#,往前台插入HTML代码

    //你的div加ID号,然后写上runat="server",变成服务器端控件,然后后台可以直接用ID号.innerhtml="html内容",这样就可以了 & ...

  7. WeFlow 简单使用教程

    一.前言 WeFlow 是什么?一个高效.强大.跨平台的前端开发工作流工具.(官网定义),下载那些你们都知道,我就不一 一介绍了.下面我说一下简单使用: 二.使用教程 首先,我们使用 WeFlow 是 ...

  8. 洛谷 - UVA11346 - 概率 Probability - 积分

    要是没学过高等数学的积分怎么办呢?可以求助于自适应辛普森法. 容易发现其实这个图形是对称的,我们只要求第一象限就可以了,第一象限如上图. 由于取点是在面积内等概率的,由高中的几何概型可知,所求概率为: ...

  9. uoj#268. 【清华集训2016】数据交互(动态dp+堆)

    传送门 动态dp我好像还真没咋做过--通过一个上午的努力光荣的获得了所有AC的人里面的倒数rk3 首先有一个我一点也不觉得显然的定理,如果两条路径相交,那么一定有一条路径的\(LCA\)在另一条路径上 ...

  10. [Xcode 实际操作]二、视图与手势-(10)UITapGestureRecognizer手势之单击

    目录:[Swift]Xcode实际操作 本文将演示使用视图的手势功能,完成视图的交互操作. import UIKit class ViewController: UIViewController { ...