当前位置: 首页 > 编程日记 > 正文

聊一聊javascript执行上下文

跟大家聊聊js的执行上下文

一,相关概念

EC : 执行上下文

ECS : 执行环境栈

VO : 变量对象

AO : 活动对象

scope chain :作用域链

二,执行上下文

javascript运行的代码环境有三种:

    全局代码:代码默认运行的环境,最先会进入到全局环境中函数代码:在函数的局部环境中运行的代码Eval代码:在Eval()函数中运行的代码
复制代码

全局上下文是最外围的一个执行环境,web浏览器中被认为是window对象。在初始化代码时会先进入全局上下文中,每当一个函数被调用时就会为该函数创建一个执行上下文,每个函数都有自己的执行上下文。来看一段代码:

    function f1() {  var f1Context = 'f1 context';  function f2() {  var f2Context = 'f2 context';  function f3() {  var f3Context = 'f3 context';  console.log(f3Context);  }  f3();  console.log(f2Context);  }  f2();  console.log(f1Context);  }  f1();
复制代码

这段代码有4个执行上下文:全局上下文和f1(),f2(),f3()属于自己的执行上下文。

全局上下文拥有变量f1(),f1()的上下文中有变量f1Context和f2(),f2()的上下文有变量f2Context和f3(),f3()上下文有变量f3Context

在这我们了解下执行环境栈ECS,一段代码所有的执行上下文都会被推入栈中等待被执行,因为js是单线程,任务都为同步任务的情况下某一时间只能执行一个任务,执行一段代码首先会进入全局上下文中,并将其压入ECS中,执行f1()会为其创建执行上下文压入栈顶,f1()中有f2(),再为f2()创建f2()的执行上下文,依次,最终全局上下文被压入到栈底,f3()的执行上下文在栈顶,函数执行完后,ECS就会弹出其上下文,f3()上下文弹出后,f2()上下文来到栈顶,开始执行f2(),依次,最后ECS中只剩下全局上下文,它等到应用程序退出,例如浏览器关闭时销毁

总结:(执行上下文就用EC替代)

    1. 全局上下文压入栈顶2. 执行某一函数就为其创建一个EC,并压入栈顶3. 栈顶的函数执行完之后它的EC就会从ECS中弹出,并且变量对象(VO)随之销毁4. 所有函数执行完之后ECS中只剩下全局上下文,在应用关闭时销毁
复制代码

大家再看一道道题:

    function foo(i) {  if(i  == 3) {  return;  }  foo(i+1);  console.log(i);  }  foo(0);
复制代码

大家明白执行上下文的进栈出栈就应该知道结果为什么是2,1,0

ECS栈顶为foo(3)的的上下文,直接return弹出后,栈顶变成foo(2)的上下文,执行foo(2),输出2并弹出,执行foo(1),输出1并弹出,执行foo(0),输出0并弹出,关闭浏览器后全局EC弹出,所以结果为2,1,0

刚才提到VO,我们来了解什么是VO

三,VO/AO

VO(变量对象)

创建执行上下文时与之关联的会有一个变量对象,该上下文中的所有变量和函数全都保存在这个对象中。

AO(活动对象)

进入到一个执行上下文时,此执行上下文中的变量和函数都可以被访问到,可以理解为被激活

谈到了上下文的创建和执行,我们来看看EC建立的过程:

    建立阶段:(函数被调用,但是还未执行函数中的代码)1. 创建变量,参数,函数,arguments对象2. 建立作用域链3. 确定this的值执行阶段:变量赋值,函数引用,执行代码
复制代码

执行上下文为一个对象,包含VO,作用域链和this

    executionContextObj = {    variableObject: { /* 函数中的arguments对象, 参数, 内部的变量以及函数声明 */ },    scopeChain: { /* variableObject 以及所有父执行上下文中的variableObject */ },    this: {}    } 
复制代码

具体过程:

    1. 找到当前上下文调用函数的代码2. 执行代码之前,先创建执行上下文3. 创建阶段:3-1. 创建变量对象(VO):  1. 创建arguments对象,检查当前上下文的参数,建立该对象下的属性和属性值2. 扫描上下文的函数申明:1. 每扫描到一个函数什么就会在VO里面用函数名创建一个属性,为一个指针,指向该函数在内存中的地址2. 如果函数名在VO中已经存在,对应的属性值会被新的引用覆盖3. 扫描上下文的变量申明:1. 每扫描到一个变量就会用变量名作为属性名,其值初始化为undefined2. 如果该变量名在VO中已经存在,则直接跳过继续扫描3-2. 初始化作用域链3-3. 确定上下文中this的指向4. 代码执行阶段4-1. 执行函数体中的代码,给VO中的变量赋值
复制代码

看代码理解:

    function foo(i) {    var a = 'hello';    var b = function privateB() {};    function c() {}    }    foo(22);
复制代码

调用foo(22)时创建上下文包括VO,作用域链,this值

以函数名作为属性值,指向该函数在内存中的地址;变量名作为属性名,其初始化值为undefined

注意:函数申明先于变量申明

    fooExecutionContext = {    variableObject: {    arguments: {    0: 22,    length: 1    },    i: 22,    c: pointer to function c(),    a: undefined,    b: undefined    },    scopeChain: { ... },    this: { ... }    } 
复制代码

创建阶段结束后就会进入代码执行阶段,给VO中的变量赋值

    fooExecutionContext = {    variableObject: {    arguments: {    0: 22,    length: 1    },    i: 22,    c: pointer to function c(),    a: 'hello',    b: pointer to function privateB()    },    scopeChain: { ... },    this: { ... }    }
复制代码

四,变量提升

    function foo() {  console.log(f1);    //f1() {}  console.log(f2);    //undefined  var f1 = 'hosting';  var f2 = function() {}  function f1() {}  }  foo();
复制代码

调用foo()时会创建VO,初始VO中变量值等有一系列的过程,所有变量初始化值为undefined,所以console.log(f2)的值为undefined。并且函数申明先于变量申明,所以console.log(f1)的值为f1()函数而不为hosting

五,总结

    1. 调用函数时会为其创建执行上下文,并压入执行环境栈的栈顶,执行完毕弹出,执行上下文被销毁,随之VO也被销毁2. EC创建阶段分创建阶段和代码执行阶段3. 创建阶段初始变量值为undefined,执行阶段才为变量赋值4. 函数申明先于变量申明
复制代码

参考:Execution Context

相关文章:

【Qt】QtCreator中使用ActionManager类管理标题栏(MunuBar)、菜单(Menu)和菜单中的项目(Action)

1、简介 QtCreator中使用ActionManager类管理标题栏(MunuBar)、菜单(Menu)和菜单中的项目(Action),下面以创建“New”动作为例,介绍ActionManager的使用方法,后续会详细分析ActionManager。 2、创建标题栏(MunuBar) const char MENU_BAR[] = "QtCreator.MenuBar&quo…

和达摩院深度绑定,阿里云下一个十年,成为“云上的阿里巴巴”

参加 2019 Python开发者日,请扫码咨询 ↑↑↑整理 | 非主流出品 | AI科技大本营(ID:rgznai100)2009 ~ 2019,阿里云已经走过了 10 年时光。在此次的阿里云峰会北京站上,为阿里云的站台的是张建锋。去年 11 月…

如何用TF Object Detection API训练交通信号灯检测神经网络?

参加 2019 Python开发者日,请扫码咨询 ↑↑↑作者简介:申泽邦(Adam Shan),谷歌认证机器学习专家(Google Developer Expert),兰州大学智能驾驶团队技术负责人,硕士在读。文…

iOS progressive Web App (PWA) 技术

随着 iOS 11.3 的发布,iOS PWA 的时代终于来了!本文对 iOS 中 PWA 的能力进行了分析,并将其与 iOS 上的 Native App、Android 上的 PWA 进行了深度对比,是值得收藏的一篇好文。 随着 iOS 11.3 的发布,苹果悄悄的支持了…

VS新建类自动添加版本注释

我们开发的时候习惯在代码顶部加上自己的版权说明。 每次拷贝挺麻烦的,上网查了一下,2003的介绍但不少。但08的模板生成方式好像改变了 后来2005的一篇介绍给了我一点提示。原来模板文件放在common7目录下。 主要分为ProjectTemplates和ItemTemplates&am…

【linux】shell中整数运算的加、减、乘、除

1、使用双括号“(( ))” shell中变量实现加法的方法 d $(($d 2)) 例子如下 #!/bin/bash d0 echo "d$d"for((i1;i<10;i)); do d$(($d 2)) echo "d$d" done unset d((i$j$k)) 等价于 iexpr $j $k ((i$j-$k)) 等价于 iexpr $j -$k ((i$…

简单使用PDO

2019独角兽企业重金招聘Python工程师标准>>> 首先基本配置&#xff1a; 连接MYSQL <?php $dsn mysql:hostlocalhost;dbnameworld;; $user user; $password secret; try { $dbh new PDO($dsn, $user, $password); } catch (PDOException $e) { echo Connecti…

一文看懂模糊搜索1.0到3.0的算法迭代历程

参加 2019 Python开发者日&#xff0c;请扫码咨询 ↑↑↑作者 | 宋广泽责编 | 郭芮来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;前一段时间在Linux上用C语言做了一个信息管理系统&#xff0c;初始版本的搜索就是直接使用了C语言库文件<string.h>里的库函数…

【linux】shell中浮点数运算的加、减、乘、除

bash 不支持浮点运算&#xff0c;如果需要进行浮点运算&#xff0c;需要借助bc,awk 处理。 1、bc #!/bin/bash#加 f$(echo "4.32.5"|bc) echo "4.32.5$f"#减 f$(echo "4.3-2.5"|bc) echo "4.3-2.5$f"#乘 f$(echo "4.30*2.50&qu…

页面加载和解析流程

输入url,浏览器向服务器发出请求&#xff0c;服务器返回html文件&#xff0c;浏览器开始载入html代码&#xff0c;发现head标签有link标签引入外部的css文件&#xff0c;浏览器发出css文件的请求&#xff0c;服务器返回这个css文件&#xff0c;浏览器继续载入body中的代码&…

作为程序员应有10项权利

Scott认为&#xff0c;作为开发人员&#xff0c;应该有权享有以下列表所示的待遇&#xff1b;不过在国内&#xff0c;这个却有点异想天开&#xff0c;能有几个老板愿意给员工如此舒适的环境呢&#xff1f; 1.每位程序员应该拥有一个安静的工作环境 2.每位程序员应该拥有听音乐…

【Qt】QtCreator中自动补全注释

1、简述 在QtCreator中编辑代码,可以自动补全函数注释,供doxygen使用并生成文档。doxygen的使用方法,后续会写一个详细的博文。 2、使用方法 在函数前分别输入“/**”、“/*!”、“//!”、“///”,然后敲击回车键,会自动补全下方函数的注释。 注意:输入的注释一定要紧…

Java内存模型与线程

一、一致性高速缓存的存储交互很好的解决了处理器与内存的速度矛盾&#xff0c;但也存在缓存一致性&#xff08;cache coherence&#xff09;问题二、java内存模型内存模型&#xff1a;对特定的内存或高速缓存进行读写访问的过程抽象。 java内存模型&#xff08;java memory mo…

Google用更少标签生成图像,还提出一个用于训练评估GAN的库

参加 2019 Python开发者日&#xff0c;请扫码咨询 ↑↑↑译者 | 刘畅责编 | 琥珀出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;生成对抗网络&#xff08;GAN&#xff09;是属于一种强有力的深度生成模型。GAN 的主要思想是训练两个神经网络&#xff1a;一个是学习如…

视频用户行为及推荐系统评价KPI-部分

问题 KPI 使用推荐区的用户数量和比率是否显著提升 使用推荐区用户量及其占比与之前进行对比 新老用户使用推荐差异是否明显 新老用户推荐区使用比率占各自类别比&#xff0c;新老用户推荐区产生的VV占各自类别比 推荐区产生的VV占总VV是否显著提升 推荐区VV占总VV占比与…

【linux】用户和组的管理:添加、修改、删除(useradd usermod userdel groupadd groupdel)

一、用户 1、添加 $ useradd -h Usage: useradd [options] LOGINuseradd -Duseradd -D [options]Options:-b, --base-dir BASE_DIR base directory for the home directory of the new account-c, --comment COMMENT 加上备注文字&#xff0c;备注文字保存在pa…

ping命令工具:同时ping多个IP

检测多个ip在同一时间点的响应状态&#xff0c;通过对比来判断哪个ip异常。 下载地址&#xff1a;https://share.weiyun.com/5XCkypG 转载于:https://www.cnblogs.com/leavind/p/8743149.html

顶会论文9篇,又斩获百度奖学金!哈工大NLP“新生代”正崭露头角

参加 2019 Python开发者日&#xff0c;请扫码咨询 ↑↑↑作者 | 琥珀出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09;“Static OnePlus”&#xff1f;首次看到这个网名时&#xff0c;激起了笔者不小的兴趣。正如每个网名背后都有一段不一样的故事&#xff0c;Static …

医院数据中心机房建设资料汇总(31篇)

医疗数据中心包括病人基本数据、入出转数据、电子病历、诊疗数据、医学影像数据、医学管理、经济数据&#xff0c;它们围绕着病人这个中心&#xff0c;成为了医 疗信息的主要来源。医疗数据质量的影响表现在医疗数据的实时、近期和远期应用&#xff0c;首先影响医疗信息系统的日…

【linux】CentOS启动后网络自动配置过程

1、启动后如何调用的网络配置脚本 网络配置脚本路径&#xff1a;/etc/init.d/network 根据不同启动级别对network脚本的调用情况&#xff1a; 进入/etc目录后&#xff0c;执行 $ find -name “*network”&#xff0c;结果如下&#xff1a; $ find -name "*network"…

web存储中cookie、session区别

http协议是一种无状态的协议&#xff0c;浏览器对服务器的每一次请求都是独立的。为了使得web能够产生一些动态信息&#xff0c;就需要保存”状态”&#xff0c;而cookie和session机制就是为了解决http协议无状态而产生。cookie是一种在客户端保存状态的方案&#xff0c;sessio…

李沐团队新作Gluon,复现CV经典模型到BERT,简单好用 | 强烈推荐

参加 2019 Python开发者日&#xff0c;请扫码咨询 ↑↑↑责编 | Jane出品 | AI科技大本营&#xff08;公众号id&#xff1a;rgznai100&#xff09;【导语】上周&#xff0c;李沐老师公布 GluonNLP0.6 版本&#xff0c;借助 Apache MXNet&#xff0c;大家可以尝试在 Gluon 中复现…

中国科学技术大学 中科大(USTC)UBUNTU源Linux镜像站IPV4/IPV6

Ubuntu下的使用方法:使用如下命令&#xff1a;sudo gedit /etc/apt/sources.list请编辑/etc/apt/sources.list&#xff0c;用下面的内容替换&#xff1a; deb http://mirrors.ustc.edu.cn/ubuntu/ natty main restricted universe multiverse deb http://mirrors.ustc.edu.cn/…

深度分析蔡徐坤的百万流量数据,揭底哪些是假的!

参加 2019 Python开发者日&#xff0c;请扫码咨询 ↑↑↑作者 | Alfred&#xff0c;毕业于暨南大学&#xff0c;数据挖掘算法工程师&#xff0c;主要研究领域为数据挖掘、机器学习来源 | Alfred数据室&#xff08;公众号id&#xff1a;Alfred_Lab&#xff09;责编 | Jane前段时…

【Linux】延时函数sleep、usleep、nanosleep、select、pselect的比较

1、简介 sleep()-------以秒为单位 #include<unistd.h> unsigned int sleep(unsigned int seconds); return&#xff1a;若进程暂停到参数seconds 所指定的时间&#xff0c;成功则返回0&#xff0c;若有信号中断则返回剩余秒数。 在linux中&#xff0c;sleep是通过nanos…

特斯拉解锁对汽车电池容量的软件限制,以帮助用户逃离飓风危险

为了对抗飓风&#xff0c;为用户提高逃生的可能性&#xff0c;特斯拉公司在此特殊情况下免费释放了电池容量限制。 据悉&#xff0c;在伊斯玛飓风抵达佛罗里达州之前&#xff0c;特斯拉为佛罗里达特斯拉的电动汽车用户更新解锁了其60kwh型号下电动汽车被封住的电池容量&#x…

nginx安装 问题 1

./configure: error: the HTTP rewrite module requires the PCRE library 有时候&#xff0c;我们需要单独安装nginx&#xff0c;来处理大量的下载请求。单独在Centos5安装nginx遇到的rewrite和HTTP cache错误解决办法&#xff1a;wget http://nginx.org/download/nginx-0.8.3…

【Qt】使用QPalette设置按钮颜色时,不生效

1、问题描述 在练习QStylePlugin示例时&#xff0c;通过插件将按钮颜色设置为红色&#xff0c;但是没有效果&#xff0c;原因是&#xff1a; 使用QPalette设置按钮颜色时&#xff0c;不生效&#xff0c;代码如下 QPalette.setBrush(QPalette::Button, Qt::red)2、问题分析 Q…

Swagger 生成 PHP restful API 接口文档

需求和背景 需求: 为客户端同事写接口文档的各位后端同学,已经在各种场合回忆了使用自动化文档工具前手写文档的血泪史.我的故事却又不同,因为首先来说,我在公司是 Android 组负责人,属于上述血泪史中催死人不偿命的客户端阵营.但血泪史却是相通的,没有自动化文档的日子,对接口…

FPGA技术的未来发展:谁与AI平分秋色

参加 2019 Python开发者日&#xff0c;请扫码咨询 ↑↑↑作者 | 老石来源 | 老石谈芯&#xff08;公众号id&#xff1a;gh_5ce1d0cb1568&#xff09;责编 | Jane任何科学技术的发展和进步都离不开两个主要的推动力量&#xff0c;一个是相关领域各大公司的研发&#xff0c;另一个…