javascript中执行环境及作用域的理解

代码星途
• 阅读 2635

执行环境(execution context,为简单起见,有时也成为“环境”)是javascript中最为重要的一个概念。执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象(variable object),环境中定义的所有变量和函数都保存在这个对象中。虽然我们编写的代码无法访问这个对象,但解析器在处理数据是会在后台使用他。

这段话中着重介绍了执行环境的这个概念,这个执行环境的作用是定义了一种行为。这种行为定义了变量或者函数访问其他数据的权限,这点和java中的设置private、protected、public等关键词的作用类似。其实这也是函数或者变量作用域的体现。然后这个概念是抽象的,机器是无法表达出抽象概念的。为了表达出这个概念,通过引入了变量对象来实现,具体实现方式是,每个执行环境都有一个和他关联的变量对象,环境中的变量和函数都存储在这个变量对象中。变量对象在机器中是某种的数据结构。所以完美的实现了抽象概念到机器代码的实现。最后本段结尾说:虽然我们编写的带代码无法访问这个对象,但在解析器(应该是js解析引擎)解析数据时,会在后台会使用到。本人觉得有点不妥,像全局执行环境我们是可以反问这个对象的。为什么说不能访问呢。这个地方值得商榷?


全局执行环境是最外围的一个执行环境。根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样。在Web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创建的。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁(全局执行环境直到应用程序退出——例如关闭网页或浏览器——时才会被销毁)。

这段介绍了全局执行环境和其关联的变量对象的实现。解析器通过Window对象来关联这个全局执行环境。全局执行环境在用户代理(一般指的是浏览器)被打开时创建,关闭时销毁。当变量对象被销毁时,存储在其内的变量或者函数也会被销毁。


每个函数在被调用时都会创建自己的执行环境。当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出,把控制权返回给之前的执行环境。ECSMScript程序中的执行流正是由这个方便的机制控制着。

这段介绍了每个函数在被调用时都会创建一个和他对应的执行环境,和这个环境关联的变量对象我们是访问不了到,但是我们可以访问其包含的一个属性(或者是变量),即arguments对象。这也解释了为什么每个函数内部,我们都可以通过arguments来访问传入的参数。最后介绍了js的执行流是通过环境栈的方式进行的。


当代码在一个环境中执行时,会创建由变量对象构成的一个作用域链(scope chain)。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在的的环境的变量对象。如果这个环境是函数,则将其活动对象(activation object)作为变量对象。活动对象在最开始时只包含一个变量,即arguments对象(这个对象在全局环境中是不存在的)。作用域中的下一个变量对象来自包含(外部)环境,而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。

这段着重介绍了作用域链,其实可以看作是环境栈(环境栈中存储的是相对应的变量对象)的另外一种表达方式。作用域链保证对执行环境有权访问的所有变量和函数的有序访问,这交代了环境栈的访问方式是从上到下访问。环境栈的顶部是当前执行的函数对应的活动对象,环境栈的底部是全局执行环境,即Window对象。


标识符解析是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,然后逐级地往后回溯,直至找到标识符为止(如果找不到标识符,通常会导致错误发生)。

作用域链的解析方式,结合环境栈的话,那么是从栈顶往下追溯,直到遇到全局执行对象。


PS:个人对执行环境的通俗理解,有错误,请包涵并指正出来。谢谢合作。

点赞
收藏
评论区
推荐文章
Dax Dax
4年前
JS核心原理理解闭包
前置概念在正式看闭包之前,我们先来学习一下前置知识,那就是JS中的作用域,我们知道,在ES5之中,作用域分为两种:全局作用域和函数作用域,随着ES6的到来,新增了块级作用域,想更好的理解闭包,那么搞清楚作用域是首要条件全局作用域我们知道,对于变量而言,我们一般会分成两类:全局变量和局部变量,一般定义在最外围环境的为全局变量,定义在函数当中的为局部变量,在we
Souleigh ✨ Souleigh ✨
5年前
JS - 作用域
一、作用域作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合换句话说,作用域决定了代码区块中变量和其他资源的可见性举个例子function myFunction(){    let inVariable  "函数内部变量";}myFunction();//要先执行这个函数,否则根本不知
Karen110 Karen110
4年前
一篇文章带你了解JavaScript作用域
在JavaScript中,对象和函数也是变量。在JavaScript中,作用域是你可以访问的变量、对象和函数的集合。JavaScript有函数作用域:这个作用域在函数内变化。一、本地JavaScript变量一个变量声明在JavaScript函数内部,成为函数的局部变量。局部变量有局部作用域:它们只能在函数中访问。JS://codeherecann
Python进阶者 Python进阶者
4年前
手把手教会你JavaScript引擎如何执行JavaScript代码
JavaScript在运行过程中与其他语言有所不一样,如果不理解JavaScript的词法环境、执行上下文等内容,很容易会在开发过程中产生Bug,比如this指向和预期不一致、某个变量不知道为什么被改了,等等。所以今天我们就来聊一聊JavaScript代码的运行过程。大家都知道,JavaScript代码是需要在JavaScript引擎中运行
Easter79 Easter79
4年前
vue 框架安装系列问题
npminstallglobalvuecli错误提示:vuecliservice'不是内部或外部命令,也不是可运行的程序或批处理文件解决:如果是npm安装的执行npmgbin把地址添加到环境变量中如果是yarn安装的执行yarnglobalbin把地址添加到环境变量中运行:yarnr
菜园前端 菜园前端
2年前
为你解惑JS作用域和作用域链知识
原文链接:变量作用域一个变量的作用域(scope)是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在JavaScript代码中的任何地方都是可以访问的。然而在函数内声明的变量只能在函数体内访问,它们是局部变量,作用域是局部性的。函数参数也是局部变
Easter79 Easter79
4年前
this到底指向啥?看完这篇就知道了!
JS中的this是一个老生常谈的问题了,因为它并不是一个确定的值,在不同情况下有不同的指向,所以也经常使人困惑。本篇文章会谈谈我自己对this的理解。this到底是啥其实this就是一个指针,它指示的就是当前的一个执行环境,可以用来对当前执行环境进行一些操作。因为它指示的是执行环境,所以在定义这个变量时,其实是不知道它真正的值的,只
御弟哥哥 御弟哥哥
4年前
彻底理解js的执行上下文,以及变量对象
在js中,执行上下文(ExecutionContext)是非常重要的一种对象,它保存着函数执行所需的重要信息,其中有三个属性:变量对象(variableobject),作用域链(scopechain),this指针(thisvalue),它们影响着变量的解析,变量作用域和函数this的指向。上下文栈(ExecutionContextS
Stella981 Stella981
4年前
Babel总结
什么是babel?babel是一个JavaScript编译器。Babel是一个工具链,主要用于将ECMAScript2015代码转换为向后兼容的旧浏览器或环境中JavaScript版本。注解:传统的编译是指转化成可执行的代码,也就是二进制代码。但是对于前端来说,因为JS是解释性语言,对于浏览器或者Node来说就是可执行的代码。
Stella981 Stella981
4年前
JavaScript基础2
普通的JavaScript对象是命名值的无序集合,JavaScript同样定义了一种特殊的对象数组array,表示带编号的值的有序集合,JavaScript为数组定义了专用的语法,使得数组具有区别于普通对象而独有的行为特性JavaScript还定义了另一种特殊对象函数,函数是具有与它相关联的可执行代码的对象,通过调用函数来运行可执行代码并返回运算结
Stella981 Stella981
4年前
JavaScript之深入理解this
定义this是函数运行时自动生成的内部对象,即调用函数的那个对象。(不一定很准确的定义,但还算通俗易懂)在大多数情况下,this的值由函数调用方式决定,它不能在执行期间赋值来设置,它在每次执行下可能都有不同的值。全局执行环境(outsidefunction)在全局执行环境中,this一直
代码星途
代码星途
Lv1
海边的夜景,美丽而又宁静,放松了人一天的好心情。
文章
4
粉丝
0
获赞
0