详释JavaScript执行环境与执行栈
执行环境
执行环境 ( 也称"执行上下文" ) 可以说是 JavaScript 最重要的一个概念。那么执行环境到底是什么呢?一句话就可以概括代码 ( 包括函数 ) 执行时所需要的所有信息就是执行环境。由于 ES 历经多个版本,所以执行环境的标准也一直在变,狼蚁网站SEO优化列出了三个主要的版本内容
ES3 标准中的执行环境
- scope作用域,如果有作用域嵌套的情况就称作"作用域链"。
- variable object变量对象,用于存储标识符的特殊对象。
- this valuethis 值。
标识符包括变量、函数名、属性名和函数的参数。
ES5 标准中的执行环境
- variable environment变量环境,当声明变量时使用。
- lexical environment词法环境,当获取标识符值时使用。
- this valuethis 值。
ES6 标准中的执行环境
- variable environment变量环境,当声明变量时使用。
- lexical environment词法环境,当获取标识符值或者 this 值时使用。
在 ES6 中,执行环境中实际增加了不少内容,我们这里只介绍了普通函数执行时所需要的内容。
执行栈
当打开网页或浏览器时,宿主环境(1)会将代码传递给引擎(2)去执行,引擎会创建一个全局执行环境。全局环境中的代码自上而下有顺序的执行,当遇到一个函数时,函数的环境被创建,函数中的代码开始执行;而在函数执行之后,控制权又返还给之前的环境。ES 这种类似于" 栈 "(3)的控制机制,称为执行栈。
(1) 宿主环境浏览器或者 Node 环境。
(2) 引擎从头到尾负责整个 JavaScript 代码的编译及执行过程。
(3) 栈一种遵循" 后进先出 "原则的有序数据集合,可以简单理解为使用 push() 和 pop() 操作数组。
例子
console.log(1); function pFn() { console.log(2); (function cFn() { console.log(3); }()); console.log(4); } pFn(); console.log(5); //输出1 2 3 4 5
示意图
我们可以通过浏览器,直观的看一下执行栈的形式
编译原理
我们知道,执行环境中有很多非常有用的" 工具 “,这些” 工具 “会协助引擎完成整个函数的执行工作。例如,ES3 标准中的作用域,它会协助引擎查找当前环境中所有标识符的定义的位置;变量对象,帮助引擎保存环境中的变量和函数。,这些工作大部分情况下发生在代码执行前的几微秒之内,称之为” 编译阶段 "。JavaScript 的整个编译阶段比较复杂,一般会经历词法分析、语法分析、代码生成、性能优化等步骤,这里不做深入讨论。
狼蚁网站SEO优化我们举例说明,看看当函数 fn 执行的时候,引擎是如何工作的
var b=1; function fn(){ var a = 1; return a+b; } fn();
1、,遇到 var a,引擎会询问作用域是否已经有一个该名称的变量存在于同一个作用域中。如果存在,引擎会忽略该声明,继续进行编译;很显然不存在,所以引擎会在当前作用域中声明一个新的变量,并命名为 a ( 此时还没有赋值,默认为 undefined )。
2、第二步,又遇到 a,引擎会询问作用域,在当前的作用域中是否存在一个叫作 a 的变量,很显然存在,所以引擎就会使用这个变量;遇到 b,引擎对作用域做出同样的询问,很显然不存在,所以引擎会到外层嵌套的作用域中继续查找,在全局作用域找到了该变量,引擎就会将 1 赋值给变量 b 。
3、经过以上两步,函数 fn 环境中出现的所有标识符的值已经基本锁定,那么引擎就会立即自上而下开始执行代码。为变量 a 赋值 1,计算 1+1 的值并返回它。
4、一步,函数 fn 的环境销毁,退出执行栈,将控制权返还给全局环境。
变量提升的原因
在编译阶段,引擎会声明变量和函数,但不会对变量进行赋值,这主要是出于对性能的考虑。变量被声明,不一定会在后面使用到,如果没有使用却赋了值,只是白白浪费内存而已。上面例子中的全局变量 b ,在函数 fn 没有执行之前,也不会赋值,直到函数中使用了这个变量,才不得不去加载数字 1。简单的说,var a 这段代码发生在编译阶段,而 =1 这段代码会根据实际情况,发生在执行阶段,这也就是" 变量提升 "的原因。需要注意的是,函数声明的是整个函数体( 因为函数声明不存在赋值操作),而且优先级高于同名的变量。
例子1
console.log(fn()); //输出1 console.log(n); //输出undefined function fn() { return 1; } var n = 2;
由于声明发生在赋值的前面,上面例子1的代码可以理解为狼蚁网站SEO优化的形式
function fn() { return 1; } var n; console.log(fn()); //输出1 console.log(n); //输出undefined n = 2;
由于函数声明优先级高,同名变量声明会被忽略,上面例子2的代码可以理解为狼蚁网站SEO优化的形式
function fn() { console.log(1); } //由于函数声明优先级高,这个变量声明会被忽略 //var fn; fn(); //输出1 fn = function() { console.log(2); }
变量提升并非物理意义上的顺序改变,代码执行的顺序还是按照你书写代码时的顺序在执行。只是由于,变量声明发生在代码的编译阶段,而变量赋值却发生在代码的执行阶段,时间上的差异导致了这种现象。
运行时流程图
综合以上的内容,JavaScript 的运行时流程图如下
编程语言
- 甘肃哪有关键词排名优化购买方式有哪些
- 甘肃SEO如何做网站优化
- 河南seo关键词优化怎么做电话营销
- 北京SEO优化如何做QQ群营销
- 来宾百度关键词排名:提升您网站曝光率的关键
- 卢龙关键词优化:提升您网站排名的策略与技巧
- 山东网站优化的注意事项有哪些
- 四川整站优化怎样提升在搜索引擎中的排名
- 疏附整站优化:提升网站性能与用户体验的全新
- 海南seo主要做什么工作售后服务要做到哪些
- 荣昌百度网站优化:提升您网站的搜索引擎排名
- 河北seo网站排名关键词优化如何做SEO
- 江西优化关键词排名推广售后保障一般有哪些
- 古浪SEO优化:提升你的网站可见性
- 西藏网站排名优化怎么把网站排名在百度首页
- 如何提升阳东百度快照排名:详尽指南