随讲变量对象和闭包一些东西

313 阅读3分钟


解释器&&AST

JS引擎在编译的时候不是一行一行编译执行的,它是一段一段的,解释器在解析分为两个过程

1.预编译时候的词法分析和语法分析
2.运行代码

这里就很简单的讲一下 预编译的时候词法分析会生成一个词法树,到语法分析的时候会把词法树转化一个抽象语法树 也就是我们常说的AST 里面就包括了我们用的语法行为,比如赋值这类操作.

抛开具体细节,简单来说就是有某种方法可以将 var a = 2; 的 AST 转化为一组机器指令,用来创建一个叫作 a 的变量(包括分配内存等),并将一个值储存在 a 中.这个行为是被分解成2个操作的.

词法作用域&&动态作用域

很多人对JS有一个误解,觉得JS跟C++ java c#一样是动态的,其实不是....JS的是静态作用域也就是词法作用域,函数在运行前执行环境就已经被确定了.因为有个JIT的缘故

两者的区别简单点说就是 词法是函数定义的执行环境,动态是执行函数当前函数的环境

上面都是基础埋点为下面做准备的

函数执行栈||环境栈(Function Stack)

栈这个概念就不解释了 基本的数据结构  FILO的模式

调用栈是干嘛的,它是用来跟踪和记录和管理执行上下文的,那么什么叫做执行上下文,

执行上下文 || 执行环境是一个比喻的词,用于描述运行Javascript代码的环境。定义了变量和函数还有其他有权访问的其他数据,还有它们的行为

PS:下面的VO和AO 表示变量对象和活动对象

_____________________________________________________________________________________________

因为是随讲, 我是按我自己的思路排的。

比如 闭包

function a(){
  var b=5;
  function c(){
     b=6
  }
  c()
}

这是一个闭包吗,从定义看它确实是一个闭包,但并不严格,我们从闭包的产生来看,闭包的特性其实是在函数定义的时候就有了,在函数定义的时候函数就会有一个[[scope]]作用域链,是的!这个是在定义的时候就有了...它包含外部对象的变量对象,比如c[[scope]]作用域链里就有a的变量对象.这个就是词法作用域

function a(){
  var b=5;
  function c(){
     b=6
  }
  return c
}

这个才是真正的闭包,因为作用域的副作用,还保留着a的变量对象,即使执行完a函数 也回收不了内存了

当我们在一个环境进行一个函数的执行的时候,就会创建一个变量对象.

变量对象的创建分为创建前和创建后,一个变量对象包括什么 一个作用域链,一个AO,一个this标志,肯定还有其他XXXX变量,但是我们日常使用中最常用的就是这3个.

创建前:

这些变量是怎么添加进去的,这就是AST和JIT的作用了,AST在创建前就会把抽象语法树解析出来从而创建一个去变量对象,这其实就是函数提升和变量提升的关键

vo={
this:xx,
A0:{
arguments:[],
函数声明,
变量声明,
},
scope:[AO,X[[Scope]]]

创建后,

其实就是解析语法树,解析个个变量的行为.然后再替换一下VO对象给个个变量赋值一下.

这里有不一样的,作用域链在创建的时候 其实只是把首部加了个自己的活动对象,第二个开始就是外部函数 外部的外部的函数 外部的外部的外部的函数的变量对象 这个时候变量对象=活动对象,也就是说添加的其实就是活动对象.就是AO.


高考语文150的散讲,谁赞成,谁反对