javascript代码怎么执行,js流程引擎

  javascript代码怎么执行,js流程引擎

  这篇文章带给你一些关于javascript的知识,包括js引擎如何执行js代码。js引擎在执行js代码的时候,还会做词法分析、语法分析、语义分析等。自顶向下,并在代码分析后生成AST。希望对你有帮助。

  推荐:javascript教程

  我们经常可以听到关于执行环境、范围、原型(链)、执行上下文等等。他们都在描述什么?

  

JS代码的运行

  我们知道js是弱类型语言,变量类型是在运行时确定的。js引擎在执行js代码时,也会处理词法分析语法分析语义分析等。自顶向下,并在代码解析后生成AST(抽象语法树),最后根据AST生成CPU可执行的机器码并执行。

  另外,JS引擎在执行代码时会做其他处理,比如V8中有两个阶段:

  编译阶段:这个阶段会创建执行上下文,包括创建变量对象(VO)(此时会初始化为未定义),建立作用域链,确定这个点。各自进入不同的操作环境。V8将创建一个新的执行上下文。执行阶段:在编译阶段创建的执行上下文被推入调用堆栈,成为正在运行的执行上下文。代码执行后,它会从调用堆栈中弹出。(下面是一个VO-AO的过程:JavaScript给变量赋值时,变量被使用,然后变量对象就会变成活动对象,转换后的活动对象就可以被访问了。)这就引出了两个概念:“执行上下文”和“作用域链”。

  

JavaScript执行上下文

  从上面我们可以知道,当js代码执行一个可执行代码时,会创建相应的执行上下文。

  首先,js中有一个与可执行代码相对应的概念:“执行环境”——全局环境、函数环境和eval。

  其次,对于每个执行上下文,有三个重要的属性:

  对象(即“VO”)范围链我们来看两段代码:

  var scope=“全局范围”;函数checkscope(){

  var scope=“本地范围”;

  函数f(){

  返回范围;

  }

  返回f();} check scope();var scope=“全局范围”;函数checkscope(){

  var scope=“本地范围”;

  函数f(){

  返回范围;

  }

  返回f;} check scope()();他们会印什么?

  为什么?答案是他们的执行上下文栈不一样!

  首先,让我们定义一个堆栈

  EStack=[global context];然后模拟第一段代码:

  estack . push(check scope function context);estack . push(f function context);estack . pop();estack . pop();第二个代码是这样的:

  estack . push(check scope function context);estack . pop();estack . push(f function context);estack . pop();原因是你可能需要先研究一下“封闭”这个概念!

  

JavaScript作用域和作用域链

  首先,作用域是指程序中定义变量的区域。作用域指定如何查找变量,即确定当前执行的代码对变量的访问权限。

  有两种范围:静态作用域动态作用域

  JS采用的静态作用域也叫“词法作用域”。函数的作用域是在定义函数时确定的。

  词法作用域中的变量会在编译过程中产生一个确定的作用域。这个范围就是“当前执行上下文”。在ES5之后,我们用“词法环境”代替作用域来描述执行上下文。词汇环境由两个成员组成:

  自词法环境记录:用于记录自词法环境中的变量和对象;外部词汇环境引用:用于记录外部词汇环境中存在的引用;我们还是来看一个例子:

  var值=1;函数foo(){

  console.log(值);}功能栏(){

  var值=2;

  foo();} bar();回头看看上面的定义,应该打印什么?

  我们来分析一下执行过程:

  在执行foo()函数时,首先要弄清楚foo函数内部是否存在局部变量值。如果不是,就根据定义时的位置,查找上面一层的代码,即value=1。因此结果将打印为1。

  当然,这不是那么简单就能概括的。可以从执行上下文的角度来分析。

  

建立作用域链

  上面我们讲了词法环境的两个组成部分(作用域)。结合执行上下文不难发现,通过对外部词法环境的引用,可以沿着栈逐层扩展范围,建立起从当前环境延伸的链式结构。

  我们再举一个例子:

  函数foo(){

  console . dir(bar);

  var a=1;

  功能栏(){

  a=2;

  } } console . dir(foo);foo();从静态范围来看,全局函数foo为自己的对象创建了一个[[scope]]属性。

  foo[[scope]]=[global context];当我们执行foo()时,会进入foo函数的定义期和执行期。在foo函数定义期间,函数栏的[[scope]]会包含全局内置范围和foo的内置范围。

  bar[[scope]]=[fooContext,global context];这就证明了这一点:“JS会通过外部的词法环境引用来创建变量对象的作用域链,从而保证对执行环境有权访问的变量和函数的有序访问。”

  让我们回头看看执行上下文中的问题。前面我们讲过两者的区别。下面是为什么他们都把“局部作用域”打印成同一句话:“JS采用词法作用域,函数的作用域取决于函数创建的位置。”3354JS函数是用作用域链执行的,这个作用域链是在定义函数时创建的。在这个作用域链中定义了嵌套函数f(),其中变量scope必须引用一个局部变量。无论f()在何时何地执行,当f()执行时,这个绑定仍然有效。

  

基于作用域链的变量查询

  当在自身的词法环境记录中找不到变量时,可以根据外部词法环境引用搜索到外层,直到最外层词法环境中的外部词法环境引用为空。

  与此类似的还有“基于对象中原型链的搜索”:

  Prototype:每个JS对象(除了null)在创建时都会与另一个对象相关联。这个物体就是我们所说的原型。每个对象都从原型“继承”它的属性。当读取实例的属性时,如果找不到,它将在与对象关联的原型中查找属性。如果找不到,它就会寻找原型的原型。直到顶级(__proto__为null)它们的区别才明显:原型链是通过原型属性建立对象继承的纽带;作用域链指的是内部函数可以访问外部函数的闭包。不管是直接的还是间接的,所有功能的范围链最终都与全局环境相联系。

  推荐:javascript学习教程以上是JavaScript引擎如何执行JS代码的详细内容。更多请关注我们的其他相关文章!

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: