首先,我们需要知道执行环境和范围是两个完全不同的概念。
函数的每次调用都有一个密切相关的范围和执行环境。从根本上说,作用域是基于函数的,而执行环境是基于对象的(比如全局执行环境就是窗口对象)。
换句话说,作用域涉及被调用函数中的变量访问,不同的调用场景是不同的。执行环境始终是该关键字的值,该关键字是对拥有当前执行代码的对象的引用。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都存储在这个对象中。虽然我们的代码不能访问这个对象,但是解析器将在处理数据时在后台使用它。
执行环境(也称为执行上下文执行上下文)
当JavaScript解释器初始化执行代码时,默认情况下首先进入全局执行环境。从现在开始,函数的每次调用都会创建一个新的执行环境。
每个函数都有自己的执行环境。当执行流进入函数时,函数的环境被推入执行堆栈。函数执行后,栈弹出它的环境,将控制权返回给前一个执行环境。ECMAScript程序中的执行流程由这种方便的机制控制。
执行环境可以分为两个阶段:创建和执行。在创建阶段,解析器首先创建一个变量对象(也称为激活对象),它由执行环境中定义的变量、函数声明和参数组成。在这个阶段,范围链将被初始化,其值将被最终确定。在执行阶段,代码被解释和执行。
演示:
脚本类型='text/javascript '函数Fn1(){函数Fn2(){ alert(document . body . tagname);//BOdy//其他代码.} Fn2();} Fn1();//此处代码/脚本
总结
浏览器加载javascript代码时,默认情况下会首先进入全局执行环境。在全局执行环境中调用并执行一个函数时,程序流进入被调用的函数,JS引擎会为该函数创建一个新的执行环境,并将其推送到执行环境栈顶。浏览器总是在栈顶执行执行环境。一旦执行完成,执行环境就会从栈顶弹出,然后进入它下面的执行环境执行代码。这样,堆栈中的执行环境将依次执行并弹出,直到它们返回到全局执行环境。
另外,注意几点:
单线程
同步执行
独特的全球执行环境
本地执行环境的数量没有限制
每次调用一个函数,都会为其创建一个新的本地执行环境,即使函数本身被多次调用(也就是说,如果一个函数被多次调用,会创建几个不同的本地执行环境)。
行动范围
当在环境中执行代码时,会创建变量对象的范围链。范围链的目的是确保有序地访问执行环境可以访问的所有变量和函数。
范围链包含对应于执行环境堆栈中每个执行环境的变量对象。通过范围链,您可以决定变量的访问和标识符的解析。
注意:全局执行环境的变量对象总是作用域链的最后一个对象。
访问变量时,一定存在可见性问题(内部环境可以访问外层的变量和函数,而外部环境不能访问内层的变量和函数)。更深入地说,当访问一个变量或调用一个函数时,JavaScript引擎会根据规则在不同的执行环境中构建一个变量对象的链表。当访问一个变量时,首先搜索链表中的第一个变量对象,如果没有找到,则继续搜索第二个变量对象,直到找到全局执行环境的变量对象,即窗口对象。这就形成了范围链的概念。
范围链图明确表达了执行环境与范围的关系(一一对应),范围与范围的关系(链表结构,自上而下的关系)。
Demo:
var color=' bluefunction change COlOr(){ var other COlOr=' red ';函数swapColors(){ var tempColor=other color;anotherColor=colorcolor=tempColor//可以在这里访问Color、otherColor和temp color }//可以在这里访问color和otherColor,但是不能访问temp color swapColors();} ChangeColor();//此处只能访问color console . log(' color now '为' color ');上面的代码包括三个执行环境:全局执行环境、changeColor()的本地执行环境和swapColors()的本地执行环境。
全局环境有一个可变颜色和一个函数change color();
changecolor()函数的本地环境有一个othercolor属性和一个swapcolors函数。当然,changecolor函数可以访问本身及其外围(即全局环境)的变量;
swapcolor()函数的本地环境有一个可变的tempcolor。上面两个环境(changecolor和window)中的所有变量都可以在函数内部访问,因为这两个环境是它的父执行环境。
上述代码的范围链如下图所示:
从上图找到的。内部环境可以通过范围链访问所有外部环境,但是外部环境不能访问内部环境中的任何变量和函数。
标识符解析(变量名或函数名搜索)是沿着作用域链逐级搜索标识符的过程。搜索过程总是从作用域链的前端开始,然后逐步返回(全局执行环境),直到找到标识符。
执行环境与范围的区别与联系
执行环境有全局执行环境和局部执行环境,局部执行环境是在函数执行过程中创建的。
作用域链是基于执行环境的变量对象,以及所有执行环境的变量对象(就函数而言,由于变量对象不能在函数执行环境中直接访问,此时激活对象(AO)起着VO(变量对象)的作用。)在一起。
在环境中执行代码时,会创建变量对象的范围链。范围链的目的是确保有序地访问执行环境可以访问的所有变量和函数。范围链的前端始终是当前执行代码所在环境的变量对象。
小运动
脚本类型=' text/JavaScript '(function(){ a=5;console . log(window . a);//未定义的var a=1;//会有变量声明推广console . log(a);//1})();/scriptwindow.a未定义,因为var a=1;发生了变量声明升级。相当于以下代码:
脚本类型=' text/JavaScript '(function(){ var a;//a是局部变量a=5;//本地环境中有,所以全局环境中的console.log(window.a)找不到。//未定义a=1;//会有变量声明推广console . log(a);//1})();/script以上是边肖带来的原生JS执行环境和范围的老套说法。希望大家多多支持我们~