每一种语言都有自己的类型,但基本上都是遵从语言的规范类型。对于一些规范类型,winter描述的并不详细。因此,在查阅相关资料后,对齐进行补充。

规范类型

共有以下7种规范类型:

  1. List和Record:List是用来描述参数列表的执行,其实跟ES中规定的数组的意义相近,但是写规范的时候还不存在ES的数组类型,所以使用List代替,写作<<1,2>>。而Record是用来描述算法中的数据聚合的,可以简单理解为ES中的对象,这类类型的话内部聚合了一个或多个命名字段(可以理解为键值对),其中命名字段的值一般是ES规范中的值或者是Record类型关联的抽象值(可以简单对应为JS中的基本类型的值或者是对象类型的值),字段的名称始终用 [[name]] 表示。你可以在JS对象的原型链上或原型链中的某个属性中看到类型的表示,例如 [[Scopes]],但一般涉及语言实现,不会对外暴露出具体信息。

  2. Set和Relation:Set主要是解释内存模型中使用的无序元素集合,即数学意义上的集合,其中的元素出现不超过一次,应该与ES6中的Set类型对应,在语言层面上会用于描述字符集之类的。Relation用于解释Set之间的关系,例如包含、交叉等,可以参考数学定义上的集合关系。

  3. Completion Record:翻译过来即是完成时的记录,这里的完成时一般是指语句执行后的完成状态。这个完成状态有几种类型,例如正常的复赋值语句完成后,他的完成状态就是normal,但例如break, continue,return, throw这些语句执行完成后,其完成状态就是对应的状态(break,continue,return,throw)。ECMAScript规范中的每个运行时语义都显式或隐式返回一个报告其结果的完成Completion Record。Completion Record是一个Record,所以就可以用对象来描述它,它有三个字段:

    1
    2
    3
    4
    5
    Completion Record = {
    [[type]] // Completion的类型,有 normal, break, continue, return, throw 5种类型
    [[value]] // 返回的值为ES语言值或空,仅当当[[type]] 为 normal,return, throw时有值
    [[target]] // 定向控制转移的目标label,为string或空,仅当[[type]] 为break, continue时有值
    }

    type 对应的是完成状态的类型。而value、target从字面理解就是完成后得到的值和需要跳转的目标,这个目标的话在我们使用 break, coutinue 的时候可以在后面跟一个 label, 来指定要跳转的模板,即 continue xxx

    只有当 type 为 [[normal]] 时,才是正常的完成状态,其他的类型均为 中断的完成状态

  4. Reference类型:用来解释诸如delete,typeof,赋值运算符,super关键字和其他语言特征等运算符的行为。 简单理解,就是如何去解析这些运算符的使用,有点类似词法作用域中对变量的LHS,RHS的查找。

    Reference一般由三个部件组成

    1
    2
    3
    4
    5
    {
    BaseValue // 值为:undefined,Object,Boolean,String,Symbol,Number,Environment Record.
    ReferencedName // String或Symbol值。
    StrictReference // 布尔值,标识是否为严格模式
    }

    举个例子:

    1
    2
    3
    const a = {
    b: true
    }

    那么在查找b的时候就会得到一个Reference类型:

    1
    2
    3
    4
    5
    {
    BaseValue: a,
    ReferencedName: b,
    StrictReference: false
    }

    这个类型从语言规范层面来说,可以解释为什么可以直接对字符串字面量使用字符串方法,例如 "ABC".toLowerCase(),要执行这个语句,就要知道"ABC".toLowerCase是什么,才能执行函数。这个语句会得到以下的Reference:

    1
    2
    3
    4
    5
    {
    BaseValue: "ABC",
    ReferencedName: toLowerCase,
    StrictReference: false
    }

    Reference内置了一些方法,对这个例子而言,对 . 运算符解释时会对 Base Value 执行 [[GetValue]] 内置方法,由于 “ABC” 是原始值类型的 (Primitive,也就是在拆箱转换的时候提到的),会对 BaseValue 进行 ToObject(BaseValue), 将其变成 String 对象,再调用 toLowerCase 方法。

    还有一些其他的内置方法,就不展开描述了。

  5. Property Descriptor类型:就是属性描述符,用来解释对象属性的特性的操作,其值为Record类型,分为数据属性描述符和访问器属性描述符。例如 [[Writable]],[[Get]]

  6. Lexical Environment和Environment Record类型:主要是用来描述ES里作用域,标识符绑定等等。这个要详细描述的话有点长,可以查询一下相关资料。关于作用域、闭包的解释都可以从这个层面来说明。

  7. Data Blocks:主要是描述二进制数据,用来描述字节大小(8位)数值的不同且可变的序列。这个我也不太懂,就不详细说明了。

结语

以上就是对 winter 对规范类型的补充说明,也是我自己刨根问底的一种尝试吧。