Js执行上下文

来源:http://www.chinese-glasses.com 作者:Web前端 人气:193 发布时间:2020-04-29
摘要:时间: 2019-09-17阅读: 123标签: 上下文概念 13-1执行上下文介绍执行上下文概念什么是执行上下文执行上下文(ExecutionContext):函数执行前进行的准备工作(也称执行上下文环境)。运行JavaScrip

时间: 2019-09-17阅读: 123标签: 上下文概念

13-1执行上下文介绍执行上下文概念什么是执行上下文执行上下文(ExecutionContext):函数执行前进行的准备工作(也称执行上下文环境)。运行JavaScript代码时,当代码执行进入一个环境时,就会为该环境创建一个执行上下文,它在运行代码前做一些准备工作,比如说:确定作用域,创建局部变量对象等。####JavaScript中执行环境1:全局环境2:函数环境3:eval函数环境(已经被淘汰)####相对应的执行上下文类型同样也有三种1:全局执行上下文2:函数执行上下文eval函数执行上下文JavaScript运行时首先会进入全局环境,对应会生成全局上下文。程序代码中基本都会存在函数,那么调用函数,就会进入函数执行环境,对应就会产生该函数的执行上下文。因为JavaScript是单线程,所以同一个时间段只能做一件任务,完成之后才可以继续下一个任务,所以就必须有一个排队机制。####JavaScript中管理多个执行上下文函数编程中,代码中会声明多个函数,对应的执行上下文也会存在多个。在JavaScript中,通过栈的存取方式来管理执行上下文,我们可称其为执行栈,或函数调用栈(CallStack)。####栈数据结构栈遵循"先进后出,后进先出"的规则,或称LIFO(“LastinFirstOut”)的规则。栈数据结构的特点:1:后进先出,先进后出2:出口在顶部,且仅有一个执行栈(函数调用栈)JavaScript中如何通过栈来管理多个执行上下文。程序执行进入一个执行环境时,它的执行上下文就会被创建,并被推入执行栈中(入栈)。程序执行完成时,它的执行上下文就会被摧毁,并从栈顶被推出(出栈),控制权交由下一个执行上下文。因为JavaScript执行中最先进入全局环境,所以处于"栈底的永远是全局环境的执行上下文"。而处于"栈顶的是当前正在执行上下文",当函数调用完成后,它就会从栈顶被推出(通常情况下,闭包会阻止该操作)。全局环境只有一个,对应的全局执行上下文也只有一个,只有当页面被关闭之后才会从执行栈中被推出,否则一直存在于栈底。至于函数上下文的个数是没有任何限制的,每到调用执行一个函数时,引擎就会自动新建出一个函数上下文。例:(functionfoo(i){if(i==3){return;}else{console.log(i);foo(++i);}})(0);//步骤如下//全局上下文//函数上下文0//函数上下文1//函数上下文2####执行上下文的生命周期执行上下文的生命周期有两个阶段:1:创建阶段(进入执行上下文):函数被调用时,进入函数环境,为其创建一个执行上下文,此时进入创建阶段。2:执行阶段(代码执行):执行函数中代码时,此时执行上下文进入执行阶段。####创建阶段的操作1:创建变量的对象函数环境会初始化创建的Arguments对象,形式参数(并赋值)普通函数声明(并赋值)局部变量声明,函数表达式声明(未赋值)2:初始化作用域链3:确定this指向(this由调用者确定)4:确定作用域(语法环境决定,哪里声明定义,就在哪里确定)####执行阶段的操作1:变量对象赋值变量赋值函数表达式赋值2:*调用函数3:顺序执行其他代码####执行上下文与作用域区别注:作用域和执行上下文并不是同一个概念执行代码时,会产生一个执行上下文环境,每次调用函数都有会执行上下文环境。当函数调用完成时,这个上下文环境以及其中的数据都会被消除(除了闭包),处于活动状态的执行上下文环境只有一个。而作用域在函数定义时就已经确定了,不是在函数调用时确定(区别于执行上下文环境,并且this也是上下文环境里的成分)//全局作用域letx=100;functionbar(){console.log(x);}//fn֢作用域functionfn(){letx=50;//bar作用域bar();}fn();//100作用域只是一个"地盘",其中没有变量。变量是通过作用域对应的执行上下文环境中的变量对象来实现的,所以作用域是静态观念的,而执行上下文环境是动态上的,两者并不一样。有闭包存在时,一个作用域存在两个上下文环境也是有的。也就是说,作用域只是用于划分你在这个作用域里面定义的变量的有效范围,出了这个作用域就无效。同一个作用域下,对同一个函数的不同的调用就会产生不同的执行上下文你环境,然而产生不同的变量的值,所以,作用域中变量的值时执行过程中确定的,而作用域是在函数创建时确定的。如果要查找一个作用域下某个变量的值,就需要找到这个作用域对应的执行上下文环境,再在其中找到变量的值。13-2变量对象以上介绍上下文的概念。整个执行上下文的生命周期包含2个阶段:建立阶段和执行阶段。当处于执行上下文的建立阶段时,可以将整个上下文环境看作是一个对象。该对象拥有3个属性例executionContextObj={variableObject:{},//变量对象,里面包含Arguments对象,形参和实参,函数和局部变量scopeChain:{},//作用域链,包含内部上下文所有变量对象的列表this:{}//上下文中this的指向对象}以上执行上下文抽象成为了一个对象,拥有3个属性,分别是变量对象,作用域链以及this指向变量对象里面所拥有的东西在函数的建立阶段,首先会建立Arguments对象。然后确定形式参数,检查当前上下文的函数声明,每当找到一个函数声明,就会在variableObject下面用函数名建立一个属性,属性值就指向该函数在内存中的地址的一个引用。如果上述函数名已经存在于variableObject(简称VO)下面,那么对应的属性值就会被新的引用给覆盖。最后,是确定当前上下文中的局部变量,如果遇到和函数名同名的变量,则会忽略该变量。函数的这两个阶段以及变量对象是如何变化的例:constfoo=function(i){vara="Hello";varb=functionprivateB(){};functionc(){}}foo(10);首先在建立阶段的变量对象如下fooExecutionContext={variavleObject:{arguments:{0:10,length:1},//确定Arguments对象i:10,//确定形式参数c:pointertofunctionc(),//确定函数引用a:undefined,//局部变量undefinedb:undefined//局部变量undefined},scopeChain:{},this:{}由此可见,在建立阶段,除了Arguments,函数的声明,以及形式参数被赋予了具体的属性值外,其他的变量属性默认的都是undefined。并且普通形式声明的函数的提升是在变量的上面的。一旦上述建立阶段结束,引擎就会进入代码执行阶段,这个阶段完成后,上述执行上下文对象如下,变量就会被赋上具体的值。fooExecutionContext={variavleObject:{arguments:{0:10,length:1},i:10,c:pointertofunctionc(),a:"Hello",//a变量被赋值为Hellob:pointertofunctionprivateB()//b变量被赋值为privateB()函数},scopeChain:{},this:{}}只有在代码执行阶段,局部变量才会被赋予具体的值。在建立阶段局部变量的值都是undefined。这其实也就是解释了变量提升的原理。加深对函数这两个阶段的过程理解(function(){console.log(typeoffoo);console.log(typeofbar);varfoo="Hello";varbar=function(){return"World";}functionfoo(){return"good";}console.log(foo,typeoffoo);})()定义一个IIFE,该函数在建立阶段的变量对象如下:fooExecutionContext={variavleObject:{arguments:{length:0},foo:pointertofunctionfoo(),bar:undefined},scopeChain:{},this:{}}首先确定Arguments对象,接下来就是形式参数,由于本例中不存在形式参数,所以接下来开始确定函数的引用,找到foo()函数后,创建foo标识符来指向这个foo()函数,之后同名的foo变量不会被创建,会直接避恶忽略。然后创建bar变量,不过初始值为undefined。建立阶段完成之后,接下来进入代码执行阶段,开始一句一句的执行代码,结果如下:(function(){console.log(typeoffoo);//functionconsole.log(typeofbar);//undefinedvarfoo="Hello";//foo被重新赋值变成一个字符串varbar=function(){return"World";}functionfoo(){return"good";}console.log(foo,typeoffoo);//Hellostring})()什么是闭包从广义上讲:所有的函数都是闭包,从狭义上讲:一个函数必须要满足两个条件,一个函数要嵌套一个内部函数,标并且内部函数要访问外部函数的变量内部函数要被外部引用为什么要使用闭包为了保持在函数内部声明的变量闭包的原理闭包就是把变量保护起来,让它不受外部污染,用一个内部函数来操作变量,在把它封装在一个外部函数中,且外部函数返回内部函数。闭包的优缺点优点1、通过闭包可以让外部环境访问到函数内部的局部变量。2、通过闭包可以让局部变量持续保持下来,不随着它的上下文环境一起销毁。缺点长时间占用容易导致内存泄漏闭包的应用防止变量命名冲突保存部分动态变量值在内存中比如经常会使用时间函数对某一个变量进行操作,如:leta=100;setTimeout(function(){console.log(++a);},10在DOM事件操作中,也经常使用闭包,如:inputtype="button"value="计数"script(function(){varcnt=0;varcount=document.getElementById("count");count.onclick=function(){console.log(++cnt);}})()/script

执行上下文,Execution Context,下面简称EC。

当函数执行时,会创建一个称为执行上下文的内部对象(可理解为作用域)。一个执行上下文定义了一个函数执行时的环境。执行栈

执行全局代码时,会产生一个全局执行上下文环境,每次调用函数都又会产生新的执行上下文环境。当函数调用完成时,这个上下文环境以及其中的数据都会被消除,再重新回到全局上下文环境。处于活动状态的执行上下文环境只有一个。

其实这是一个压栈出栈的过程——执行上下文栈。

全局执行上下文环境一定是在栈底,在浏览器关闭后出栈。

组成生命周期

事例代码:

本文由10bet发布于Web前端,转载请注明出处:Js执行上下文

关键词:

上一篇:【10bet】js之yeild

下一篇:没有了

最火资讯