当前位置: 首页 > Web前端 > HTML5

JavaScript之执行环境与作用域的区别与联系

时间:2023-04-05 20:30:00 HTML5

执行环境与JavaScript领域作用域的区别与联系。js没有块级作用域是什么意思?花括号中的一对语句代码集如何属于一个块,其中定义的所有变量在代码块外都是不可见的,这称为块级作用域。范围控制变量和参数的可见性和生命周期。块级作用域的概念,任何在一对花括号({和})中设置的语句都属于一个块,其中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。在js中,作用域分为全局作用域和函数作用域。没有块级作用域的概念,ECMAScript6(简称ES6)中加入了块级作用域。块作用域被{}包含,if语句和for语句中的{}也属于块作用域。我们都知道js中没有块级作用域,而ES6中加入了块级作用域,那么块级作用域有什么好处呢?执行环境定义函数可以访问的变量或其他数据,确定它们各自的行为。执行环境,又称“环境”、执行上下文或执行上下文对象,统一用执行上下文来表示,它定义了变量或函数可以访问的其他数据,并决定了它们各自的行为。js代码执行的环境。每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都存储在这个对象中。执行环境的特点JavaScript中有三种执行环境:第一种是:全局执行环境,也就是最外围的执行环境。加载代码后,引擎首先进入该环境。在浏览器中,全局环境是window对象,因此所有全局属性和函数都是作为window对象的属性和方法创建的。直到应用程序退出,全局执行环境才被破坏。每个函数都有自己的执行环境。当执行流进入函数时,函数的环境将被压入环境堆栈。执行完后栈会把它弹出来,把控制权交给之前的执行环境。.二是:函数执行环境。当执行流执行一个函数时,JavaScript会创建一个新的函数执行环境。函数执行环境中的代码执行完毕后,环境就会被销毁,其中存储的所有变量和函数都会被销毁。定义也被破坏。如果环境是一个函数,它的活动对象被用作变量对象。活动对象一开始只有一个变量,即arguments对象。这个对象不存在于全局环境中,只存在于函数中。第三个是:eval执行环境。用eval执行的语句应该和普通的语句没什么区别,作用域就是当前作用域。默认情况下:1.eval中的代码可以读取和使用范围内的变量2.eval中声明的变量也可以存在于当前范围内示例:(function(){window.eval("varx=1;");})();警报(x);//1x在窗口中声明(function(){eval("varx=1;");alert(x);//1})();警报(x);//x未定义在闭包中声明(function(){"userstrict";eval("vary=1;alert(y);");//1alert(y);//y不是定义})();警报(y);//yisnotdefined严格模式下eval的变量只存在于eval内部,不会泄露。作用域链的前端始终是当前执行代码所在环境的变量对象。执行顺序varfoo=function(){console.log('foo1');}foo();//foo1varfoo=function(){console.log('foo2');}foo();//foo2functionfoo(){console.log('foo1');}foo();//foo2functionfoo(){console.log('foo2');}foo();//foo2JavaScript引擎不是逐行分析执行程序,而是一段一段地分析执行。第一个示例中有变量提升,第二个示例中有函数提升。JavaScript中的可执行代码分为三种,全局代码、函数代码和eval代码。执行上下文在JavaScript引擎中创建一个执行上下文栈来管理执行上下文。functionfun3(){console.log('fun3')}functionfun2(){fun3();}functionfun1(){fun2();}fun1();当执行一个函数时,会创建一个执行上下文,然后将其压入执行上下文栈中。当函数执行时,函数的执行上下文将从栈中弹出。Scope作用域是指程序中定义变量的区域。作用域指定了当前正在执行的代码如何查找变量以及对变量的访问权限。关于词法作用域和动态作用域词法作用域是静态作用域,相对于词法作用域是动态作用域。词法作用域是在定义函数时确定的,而动态作用域是在调用函数时确定的。varvalue=1;functionfoo(){console.log(value);}functionbar(){varvalue=2;foo();}bar();scopechain作用域链,当代码在一个环境中执行时,会创建一个变量对象的作用域链,以确保有序访问执行环境可以访问的所有变量和函数。每次执行流进入执行环境时,都会创建一个作用域链。作用域链由执行环境的变量对象组成。作用域链的前端是当前执行环境的变量对象。下一个变量对象来自外围环境,下一个变量对象来自下一个外围环境,一直持续到全局执行该环境的变量对象。所以全局执行环境的变量对象永远是作用域链中的最后一个对象。内部环境可以通过作用域链访问所有外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些环境之间的连续性是线性和有序的。每个环境都可以向上搜索作用域链,但是任何环境都不能通过向下搜索作用域链进入另一个执行环境。当我们需要在一个环境中读取并引用一个标识符来表示某种含义时,我们必须通过搜索来确定标识符。从近到远,从局部到全局搜索,如果查询到对应的标识符,则停止搜索。有两种类型的扩展范围链执行环境:全局和本地。Extension是一种方法,可以在作用域链的前端临时增加一个变量对象,代码执行完后会移除这个变量对象,从而拉长作用域链。第一个是try-catch语句的catch块。通过在作用域的前面添加一个变量对象,它在代码执行结束后被销毁。第二个是with语句。将指定的对象添加到作用域链以扩展作用域链。try{null.name}catch(e){console.log(e.message);}扩展作用域链的特点:首先,添加的变量对象是临时的,语句执行完后会被移除。其次,添加的变量对象与执行环境无关。比如with语句接收到一个参数location对象,那么它的变量对象就包含了location对象的所有属性和方法,这个变量对象被添加到作用域链的前端。没有块级作用域因为没有块级作用域,但是添加了块级作用域,为什么要添加这个功能呢?你必须了解当ES5没有块级作用域时会发生什么问题。首先,在if或for循环中声明的变量会泄漏到全局变量中,其次,内部变量可能会覆盖外部变量。懂js的同学都知道,ES5中没有块级作用域的概念,只有全局作用域和函数作用域。以前js使用var定义的变量。如果使用js内部已经定义好的函数名,会造成全局污染。如果使用了同名变量,会覆盖之前的变量,或者函数内部的变量会覆盖外部的变量。从无块作用域到块作用域。JavaScript没有块级作用域,这常常导致理解上的混乱。为什么js没有块级作用域if(true){vardada='dada';}console.log(达达);//dada即使不在if块中也可以访问为什么执行完if语句后没有销毁?JavaScript中if语句中的变量声明将变量添加到当前执行环境。for(vari=0;i<10;i++){doSomething(i);}警报(我);//10在JavaScript中,for语句创建的变量i在循环外的执行环境中,即使for循环结束后,仍然会存在于for循环中。JavaScript没有块级作用域,变量的声明周期与执行环境有关。使用var声明的变量会自动添加到最近的环境中,也就是我们所说的函数局部环境。在with语句中,最接近的环境是函数环境。如果变量在初始化时没有用var声明,则该变量会自动添加到全局环境中。与内容块级作用域的出现相辅相成的是,es6语法中有两种定义变量的方法:let和const。let定义了一个允许改变的变量,只作用于定义时的作用域,const也是,但唯一的const是不允许改变的。执行环境与作用域的区别与联系作用域链以执行环境的变量对象为基础,由执行环境的所有变量对象组成。(function(){a=5;console.log(window.a);//undefinedvara=1;//会发生变量声明提升console.log(a);//1})();(function(){vara;//a是一个局部变量a=5;//如果局部环境中有a,则不会查找全局console.log(window.a);//undefineda=1;//这里发生变量声明提升console.log(a);//1})();Eval:在字符串中执行代码内置函数eval允许我们在字符串中执行代码。语法如下:letresult=eval(code);例如:letcode='alert("Hello")';eval(code);//Hello字符串中的代码是在当前词法环境下执行的,所以可以访问外部变量:leta=1;functionf(){leta=2;eval('警报(a)');//2}f();letx=5;eval("x=10");alert(x);//10、变量的值发生了变化。总结全局执行环境是最外围的执行环境。根据其所在的宿主环境不同,代表执行环境的对象也不同。在网络浏览器中,全局执行环境被认为是窗口对象,所有全局变量和函数都被创建为窗口对象的属性和方法。当一个执行环境中的所有代码执行完毕后,这个环境就被销毁了,其中存储的所有变量和函数定义也被销毁了。Eval的执行环境与函数调用的执行环境相同。执行环境可以分为两种,一种是全局执行环境,一种是函数执行环境。全局执行环境是最外层的执行环境。每个函数都有自己的执行环境。函数执行环境的变量对象称为活动对象。它一开始只包含一个变量,即arguments对象。标识符解析是沿着作用域链逐一查找标识符的过程,从作用域链的前端开始,一直回溯,直到找到标识符。如果找不到,则会发生错误。每次进入新的执行环境时,都会创建一个作用域链来搜索变量和函数。变量的执行环境有助于确定何时应释放内存。补充内容context和scope,每一个函数调用都有一个scope和context与之关联,scope基于函数,context基于变量对象。调用函数时,通过new操作符创建一个对象的实例,this指向新创建的实例。作用域与每次调用函数时变量的访问有关。每个调用都是独立的。上下文始终是关键字this的值,它是对调用当前可执行代码的对象的引用。☆END☆参考文档来源:《JavaScript 高级程序设计》加群前端交流群扫码,备注加群-技术领域-城市-名称当前文章内容涉及前端知识点,包括Vue、JavaScript、数据结构与算法,实战演练,Node全栈前端技术,紧跟行业发展步伐,将web前端领域和网络原理以通俗易懂的方式呈现给小伙伴。更多信息请到达达前端网站学习:www.dadaqianduan.cn推荐阅读1.你对这个了解多少,new,bind,call,apply?那我告诉你2.为什么要学JavaScript设计模式,因为它是核心3.一篇文章带你走进JavaScript中的闭包和高级函数4.大厂HR面试ES6深度面试题的知识点感受那这篇文章对你有帮助吗?请分享给更多人关注“达达前端”,加star提升前端技能。这是一种品质和态度公众号