Javascript执行环境和作用域的注意要点

  • A+
所属分类:JavaScript

 

执行环境

执行环境就是“环境”,是js中最重要的概念。执行环境定义了变量或函数有权访问的其他数据。每个执行环境都有一个与之相关的变量对象(我们编写的代码无法访问这个对象)。

  • 全局执行环境(是最外围的执行环境。在Web浏览器中,全局执行环境是Window对象。某个执行环境中的所有代码执行完毕后,该环境会被销毁;全局执行环境则直到应用程序退出,如关闭网页或浏览器时才会被销毁。环境被销毁时,保存在其中的所有变量和函数定义也都会被销毁。)
  • 执行环境(当执行流进入一个函数时,函数的环境会被推入一个环境栈中。当函数执行之后,环境栈将其弹出,把控制权返回给之前的执行环境。)
  • 作用域链(当代码在一个环境中执行时,会创建变量对象的一个作用域链。其用途是保证对执行环境有权访问的所有变量和函数的有序访问。一个包含环境的变量对象到另一个包含环境的变量对象,最后到全局执行环境的变量对象。所以,全局执行环境的变量对象始终都是作用域链中的最后一个对象。)
标识符解析

标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程从作用域链的最前端开始,逐级向后回溯,直到找到标识符为止。如:

在上面的例子中,函数changeColor()的作用域链包含两个对象:changeColor()函数自己的变量对象和全局环境的变量对象。(可以在函数内部访问变量color,就是因为可以在这个作用域链中找到它。)在看另一个例子:

  • 执行环境:3个,全局环境,changeColor()的局部环境和swapColors()的局部环境。
  • 全局环境:一个变量color 和一个函数changeColor()。
  • changeColor()环境:一个变量anotherColor 和一个swapColors()函数。(可以访问全局变量中的color)
  • swapColors()环境:一个变量tempColor。(可以访问全局环境中的color 和changeColor()环境中的anotherColor变量。)
    swapColors()内部可以访问到其他两个环境中的所有变量,因为其他两个环境是它的父执行环境*

上面的例子可以用作用域链表示出来:(话说有没有网友可以推荐下好用的图床呀?纯文本画画还真麻烦。)

内部环境可以通过作用连访问所有的外部环境,但外部环境不能访问内部环境的任何变量和函数。就是说,每个环境都可以向上搜索作用域链,但任何环境都不能向下搜索作用域链。

延长作用域链

虽然执行环境的类型总共只有全局和局部(函数)两种,但是还是可以使用下面两种办法来延长作用域链。

  • try-catch 语句的catch 块;
  • with 语句
    上面这种方法就是当执行流进入下列任何一个语句时,作用域链就会得到加长。如:

这里面使用with 语句,可以看到return url 语句可以访问到with 语句中的url 变量。再看下面的例子:

如果是普通的function 函数则不能访问url 变量。

另外,在IE8 中,即使是在catch 块的外部也可以访问到错误对象。IE9 修复了这个问题。

没有块级作用域

JavaScript 不像C 语言中,由花括号封闭的代码块都有自己的作用域。JavaScript 没有块级作用域。如:

花括号以外的地方仍然可以访问话括号内的变量。

尤其应该在for 循环中注意这个特性:

声明变量

如果初始化变量时没有使用var 声明,该变量会被添加到全局环境中去。如:

在编写代码的过程中,不声明而直接初始化变量是一个常见的错误做法。很可能会导致以外。建议在初始化变量之前,一定要先声明。在严格模式下,初始化未经声明的变量会导致错误。

查询标识符

搜索过程就是沿作用域链向上查询的过程。如:

如果局部环境中存在着同名标识符,就不会使用位于父环境中的标识符。如:

weinxin
我的微信公众号
我的微信公众号扫一扫

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: