资讯专栏INFORMATION COLUMN

JavaScript 作用域和作用域链学习

史占广 / 1119人阅读

摘要:作用域与作用域链每个函数都有自己的执行环境。这是初步了解作用域,如想更深入了解作用域,请看下面链接作用域原理作用域链由一道题图解的作用域或者看权威指南和高级程序设计

本文是我学习JavaScript作用域整理的笔记,如有不对,请多指出。

作用域

一个变量的作用域是程序源代码中定义这个变量的区域。

而在ES5中只分为全局作用域和函数作用域,也就是说for,if,while等语句是不会创建作用域的。ES6(let,const)除外。

    //全局作用域
   var a = 123;
   function aa () {
       //局部作用域
       var b = 456;                            
   }
声明提前

JavaScript函数里声明的所有变量(但不涉及赋值)都被“提升”至函数体的顶部,在代码开始运行之前。这个特性被称为声明提前。

    var a = "g";
    function f() {
      console.log(a); //输出undefined
      var a = "l";
      console.log(a); //输出"l"
    } 

由于函数作用域的特性,局部变量在整个函数体始终是有定义的,也就是说,函数体的局部变量覆盖了同名全局变量。在函数体内,变量a被“提前”了,提前至函数体的顶部,所以第一次输出的是undefined,那时候还没赋值,但代码执行到var语句时候,局部变量才会被赋值。因此第二次输出则是“l”。此代码过程如下:

    var a = "g";
    function f() {
        var a; 
        console.log(a); //输出undefined
        a = "l";
        console.log(a); //输出"l"
   } 

因此一些程序员特意将变量声明放在函数体的顶部,而不是将声明靠近放在使用变量之处。

作用域链

先看一段简单代码,代码如下:

var name = "wythe";
function one () {
    console.log(name); //wythe
    var firend = "zero";
}
one();
console.log(firend); //报错

看到代码可知,name是在全局作用域中声明的全局变量,而firend则是在函数作用域中声明的局部变量。在执行时候你会发现函数作用域能够访问到在全局作用域中name这个变量,而全局作用域却不能访问到函数作用域的friend的变量,原因是作用域链!
作用域链的规则:
外部不能访问内部变量,内部可以访问外部变量
为什么会有这样规则?因为是执行环境所规定的。

执行环境定义了变量或函数有权访问其他数据,决定了它们的行为。每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。
全局执行环境是最外围的一个执行环境。在Web浏览器中,全局执行环境被认为是window对象。某个执行环境中所有所有代码执行完毕后,该环境被销毁,保存在其中的所有的变量和函数定义也随之销毁。

补充说明:需要了解一些概念,变量对象(Variable Object)、活动对象(Activation Object)、函数的属性[[scope]].

变量对象指的是变量对象(缩写为VO)是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的内容有:变量 (var, 变量声明)、函数声明和函数的形参。

执行上下文(执行环境):每次当控制器转到ECMAScript可执行代码的时候,即会进入到一个执行上下文。执行上下文(简称-EC)是ECMA-262标准里的一个抽象概念,用于同可执行代码(executable code)概念进行区分。

活动对象指的是由函数的运行期上下文(代码执行前)创建,在运行时可变,初始时只有 arguments 属性,通过变量的初始化,包含了局部变量、命名参数、 this 等

汤姆大叔深入理解JavaScript变量对象

函数属性[[scope]]指的是函数对象都有一个内部属性 [[scope]],函数被创建后,函数 [[scope]] 属性会被创建此函数的作用域中可访问的数据对象填充,是所有父变量对象的层级链。[[scope]] 在函数被创建时静态存储,永远不会改变,直至销毁。

作用域与作用域链

每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将环境弹出,把控制权返回之前的执行环境。当代码在一个环境执行时候,会创建变量对象的一个作用域链(scope chain)。作用域的前端,始终都是当前执行的代码所在环境的变量对象。如何这个环境是函数,则将其活动对象(activation object)作为变量对象。活动对象在最开始只包含一个变量,即arguments对象(这个对象在全局环境是不存在)。作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含对象。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域中的最后一个对象。
根据这个概念图解上面代码:

在函数one创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,当执行流执行到one()语句时,会创建函数one执行环境。将函数one执行环境。如果这个环境是函数,则创建一个活动对象,然后此对象会被推入作用域链的前端,当函数执行完毕后,活动对象也随之销毁。新的作用域链如下图所示:

标识符解析是沿着作用域一级一级地搜素标识符的过程。搜素过程始终从作用域的前端开始,然后逐级地向后回溯,直到找到标识符为止,找不到,会导致错误发生。内部环境可以通过作用域链访问所有外部环境,但外部环境不能访问内部环境中任何变量和函数。这些环境之间的联系是线性,有次序的。

这是初步了解作用域,如想更深入了解作用域,请看下面链接:
JavaScript作用域原理
JavaScript作用域链
由一道题图解JavaScript的作用域
或者看《JavaScript权威指南》和《JavaScript高级程序设计》

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86548.html

相关文章

  • 深入学习js之——作用域链

    摘要:开篇作用域是每种计算机语言最重要的基础之一,因此要想深入的学习作用域和作用域链就是个绕不开的话题。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。这时候执行上下文的作用域链,我们命名为至此,作用域链创建完毕。 开篇 作用域是每种计算机语言最重要的基础之一,因此要想深入的学习JavaScript,作用域和作用域链就是个绕不开的话题。 在《深入学习js之—-执行上下文栈》中我们提到...

    lemanli 评论0 收藏0
  • javascript中关于作用域和闭包

    摘要:在代码执行时,对应的作用域链常常是保持静态的。当语句执行完毕后,会把作用域链恢复到原始状态。在全局作用域中创建的函数,其作用域链会自动成为全局作用域中的一员。 列表项目 前言 学习了javascript已经很久了,关于这个语言中的这两个特性也是早已耳熟能详,但是在实际的使用的过程中或者是遇到相关的问题的时候,还是不能很好的解决。因此我觉得很有必要深入的学习并且记录这个问题,以便在今后的...

    zacklee 评论0 收藏0
  • 深入学习js之——词法作用域和动态作用

    摘要:在中的应用采用词法作用域,也就是静态作用域。那什么又是词法作用域或者静态作用域呢请继续往下看静态作用域与动态作用域因为采用的是词法作用域函数的作用域在函数定义的时候就决定了。 开篇 当我们在开始学习任何一门语言的时候,都会接触到变量的概念,变量的出现其实是为了解决一个问题,为的是存储某些值,进而,存储某些值的目的是为了在之后对这个值进行访问或者修改,正是这种存储和访问变量的能力将状态给...

    shiweifu 评论0 收藏0
  • JS学习笔记(第4章)(变量、作用域和内存问题)

    摘要:具体来说就是当执行流进入下列任何一个语句时,作用域链就会得到加长语句的块和语句。这两个语句都会在作用域链的前端添加一个变量对象。对来说,会将指定的对象添加到作用域链中。 1. 基本类型和引用类型的值 JavaScript变量可以用来保存两种类型的值:基本类性值和引用类性值。基本类型值源自以下5种基本数据类型:Undefined、Null、Boolean、Number和String。基本...

    linkin 评论0 收藏0
  • 理解JavaScript中的作用域和作用域链

    摘要:示例当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。每一个运行期上下文都和一个作用域链关联。此时,作用域链中函数的所有局部变量所在的作用域对象会被推后,访问代价变高了。 作用域 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。 作用域链 函数对象有一个内部属性[...

    XanaHopper 评论0 收藏0

发表评论

0条评论

史占广

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<