详细解释JavaScript执行环境和执行栈
执行环境
执行环境(也叫‘执行上下文’)可以说是JavaScript最重要的概念。那么到底什么是执行环境呢?可以用一句话来概括:代码(包括函数)时需要的所有信息都是执行环境。由于ES经历了多个版本,执行环境的标准也在不断变化。列出了以下三个主要版本:
ES3标准中的执行环境
范围:范围。如果存在范围嵌套,则称为“范围链”。变量对象:用于存储标识符的特殊对象的变量对象。这个值:这个值。*标识:包括变量、函数名、属性名和函数参数。
ES5标准中的执行环境
变量环境:变量环境,在声明变量时使用。词法环境:词法环境,获取标识符值时使用。这个值:这个值。ES6标准中的执行环境
变量环境:变量环境,在声明变量时使用。词法环境:词法环境,在获取标识符值或该值时使用。*在ES6中,执行环境中实际上已经添加了很多内容,我们只介绍执行普通功能时需要的内容。
执行栈
当打开网页或浏览器时,宿主环境(1)将把代码传递给引擎(2)执行,引擎将首先创建一个全局执行环境。全局环境中的代码从上到下依次执行。遇到函数时,创建函数的环境,函数中的代码开始执行;函数执行后,控件返回到以前的环境。ES是一种类似‘栈’(3)的控制机制,称为执行栈。
(1)主机环境:浏览器或Node环境。(2)引擎:负责从头到尾编译执行整个JavaScript代码。(3) Stack:遵循‘后进先出’原则的有序数据集,可以简单理解为使用push()和pop()操作数组。
示例:
console . log(1);函数PFn(){ console . log(2);(函数CFn(){ console . log(3));}());console . log(4);} PFn();console . log(5);//输出:1 2 3 4 5原理图:
我们可以通过浏览器直观地查看执行堆栈的形式:
编译基础
我们知道,执行环境中有很多非常有用的工具,这些工具将帮助引擎完成整个功能的执行。例如,ES3标准中的范围将帮助引擎找到当前环境中所有标识符的定义位置;变量对象帮助引擎保存环境中的变量和函数。当然,这些任务大多发生在代码执行前的几微秒内,这被称为“编译阶段”。JavaScript的整个编译阶段比较复杂,一般要经过词法分析、语法分析、代码生成、性能优化等步骤,这里不做深入讨论。
让我们举个例子来看看函数fn执行时引擎是如何工作的:
var b=1;函数fn(){ var a=1;返回a b;} fn();1.首先,当遇到var a时,引擎会询问在同一个作用域中是否已经有一个同名的变量。如果存在,引擎将忽略声明并继续编译;显然它不存在,所以引擎会在当前范围内声明一个新的变量,并将其命名为A(此时还没有赋值,默认值未定义)。
2.第二步,当再次遇到A时,引擎首先会询问作用域当前作用域中是否有一个名为A的变量,这个变量显然是存在的,所以引擎会使用这个变量;遇到B时,引擎会对作用域进行同样的查询,这显然是不存在的,所以引擎会继续在外部嵌套作用域中搜索,当在全局作用域中找到变量时,引擎会给变量B赋值1。
3.经过以上两个步骤,函数fn环境中出现的所有标识符的值已经基本锁定,所以引擎会立即从上到下开始执行代码。给变量A赋值1,计算值1 1并返回。
4.最后一步,破坏函数fn的环境,退出执行栈,控制权返回全局环境。
可变晋升的原因
在编译阶段,引擎声明变量和函数,但不为变量赋值,这主要是出于性能考虑。变量已声明,但以后可能不会使用。如果不使用,就给它们赋值,这只是浪费内存。在不执行函数fn之前,不会分配上面示例中的全局变量b,在函数中使用该变量之前,必须加载数字1。简单来说,代码var a发生在编译阶段,而代码=1根据实际情况发生在执行阶段,这就是‘变量提升’的原因。另外需要注意的是,函数声明了整个函数体(因为函数声明中没有赋值操作),优先级高于同名变量。
例1:
console . log(fn());//输出:1 console . log(n);//输出:undefinedffunction fn(){ return 1;} var n=2;由于声明发生在赋值之前,所以上面示例1的代码可以理解为以下形式:
函数fn(){ return 1;} var n;console . log(fn());//输出:1 console . log(n);//输出:undefinedn=2;因为函数声明具有高优先级,所以同名的变量声明将被忽略。以上示例2的代码可以理解为以下形式:
函数fn(){ console . log(1);}//因为函数声明具有高优先级,所以这个变量声明将被忽略。//var fn;fn();//输出:1fn=function(){ console . log(2);} *变量提升不是物理顺序的改变,而是代码执行的顺序仍然是你写代码时的顺序。只是因为变量声明发生在代码的编译阶段,而变量赋值发生在代码的执行阶段,这种现象是时差造成的。
运行时流程图
综上所述,JavaScript的运行时流程图如下:
版权声明:详细解释JavaScript执行环境和执行栈是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。