当前位置:首页 > 科技  > 软件

深入理解 Babel - 微内核架构与 ECMAScript 标准化

来源: 责编: 时间:2024-09-10 09:51:09 34观看
导读随着浏览器版本的持续更新,浏览器对JavaScript的支持越来越强大,Babel的重要性显得较低了。但Babel的设计思路、背后依赖的ECMAScript标准化思想仍然值得借鉴。本文涉及的Babel版本主要是V7.16及以下,截至发文时,Babel最

随着浏览器版本的持续更新,浏览器对JavaScript的支持越来越强大,Babel的重要性显得较低了。但Babel的设计思路、背后依赖的ECMAScript标准化思想仍然值得借鉴。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

本文涉及的Babel版本主要是V7.16及以下,截至发文时,Babel最新发布的版本是V7.25.6,未出现大版本更新,近2年也进入了稳定迭代期,本文的分析思路基本适用目前的Babel设计。k0i28资讯网——每日最新资讯28at.com

一、Babel简介

k0i28资讯网——每日最新资讯28at.com

Babel是什么

k0i28资讯网——每日最新资讯28at.com

Babel是JavaScript转译器,通过Babel,开发者可以自由使用下一代ECMAScript 语法。高版本ECMAScript语法将被转译为低版本语法,以便顺利运行在各类环境,如低版本浏览器、低版本 Node.js 等。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

Babel 是转译器,不是编译器。下面是转译和编译的区别:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

编译,一般指将一种语言转换为另一种语法和抽象程度等都不同的语言,常见的比如 gcc 编译器。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

转译,一般指将一种语言转换为不同版本或者抽象程度相同的语言,比如 Babel 可以把 ECMAScript 6 语法转译为 ECMAScript 5语法。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

利用 Babel,开发者可以使用 ECMAScript 的各种新特性进行开发,同时花极少的精力关注浏览器或其他JS运行环境对新特性的支持。甚至,开发者可以根据自身需要,创造属于自己的 JavaScript 语法。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

Babel在转译的时候,会对源码进行以下处理: 语法转译(Syntax)和添加API Polyfill。k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

  • 语法(Syntax)部分Babel 支持识别高版本语法,并通过插件将源码从高版本语法转译为低版本语法,如:

k0i28资讯网——每日最新资讯28at.com

箭头函数 () => {} 转为普通函数 function() {}。k0i28资讯网——每日最新资讯28at.com

const / let 转译为vark0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • API Polyfill有些运行时相关的 API,语法转译无法解决它们对低版本浏览器等环境的兼容性问题,因此 Babel 通过与 core-js 等工具的配合,实现 API 部分对目标环境(通常是低版本浏览器等)的兼容。例如[1, 2, 3].include、Promise等 API,Babel 在处理时,如果目标环节可能不支持原生的 include / Promise 的话,Babel 会在转译结果中嵌入 include / Promise 的自定义实现。有多种方式可以使用 Babel,如: 命令行(babel-cli、babel-node)、浏览器(babel-standalone)、API 调用(babel-core)、webpack loader(babel-loader)等。

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

转译过程

k0i28资讯网——每日最新资讯28at.com

和多数转译器相同,Babel 运行的生命周期主要是 3 个阶段: 解析、转换、代码生成。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

这个过程涉及抽象语法树:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

抽象语法树(Abstract Syntax Tree,AST),或简称语法树(Syntax tree),是源代码语法结构的一种抽象表示。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

AST 是树形对象,以结构化的形式表示编程语言的语法结构,树上的每个节点都表示源代码中的一种结构。k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

源码字符串需要经转译器生成 AST,转译器有很多种,不同转译器,生成的AST对象格式细节可能有差异,但共同点为: 都是树形对象、该树形对象描述了节点特征、各节点之间的关系(兄弟、父子等)。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

以下是 Babel 生命周期的三个过程:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • 解析(Parsing): Code1 ==> 抽象语法树1解析过程包括 2 个环节: 词法解析、语法解析,最终生成抽象语法树。词法解析阶段,代码字符串被解析为 token 令牌数组,数组项是一个对象,包括: 代码字符碎片的值、位置、类型等信息。token 数组是平铺式的数组,没有嵌套的结构信息,它是为语法解析阶段做准备的。语法解析阶段,token 令牌数组被解析为结构化的抽放语法树对象(AST)。babel-parser 完成该阶段的主要功能。

图片图片k0i28资讯网——每日最新资讯28at.com

  • 转换(Transformation): AST1 ==> AST2Babel 生成 AST 后,会对 AST 进行遍历,遍历过程中,各类插件对原 AST 对象进行增删改查等操作,AST 结构被修改。

图片图片k0i28资讯网——每日最新资讯28at.com

  • 代码生成(Generation): AST2 ==> Code2Babel 将修改后的 AST 对象转目标代码字符串。babel-generator 完成该阶段的主要功能。

图片图片k0i28资讯网——每日最新资讯28at.com

二、Babel微内核架构

k0i28资讯网——每日最新资讯28at.com

微内核架构

k0i28资讯网——每日最新资讯28at.com

Babel 采用微内核架构,其内核保留核心功能,其余功能利用外部工具和插件机制实现,也体现了"开放-封闭"的设计原则。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

除了微内核设计架构,Babel 的模块设计也可以做如下分类:k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

转译模块

k0i28资讯网——每日最新资讯28at.com

转译模块位于 Babel 微内核架构的"微内核"部分,该部分主要负责代码转译,也就是上面提到的"解析-转换-代码生成"过程。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

该模块主要包括: babel-parser、babel-traverse、babel-generator。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-parser负责将代码字符串转为 AST 对象。有 2 点值得一提:

k0i28资讯网——每日最新资讯28at.com

babel-parser 本身并不会对 AST 做转换操作,只是负责解析出 AST。AST 转换部分交由各类 plugins 和 presets 处理。k0i28资讯网——每日最新资讯28at.com

babel-parser 内置了对 ESNext/TypeScript/JSX/Flow 最新版本语法的支持,但很多默认是不开启的,目前没有开放插件机制扩展新语法。k0i28资讯网——每日最新资讯28at.com

  • babel-traverse在转译过程中,babel-traverse 负责遍历 AST 节点,并根据配置的 plugins/presets,在遍历过程中,对各个 AST 节点进行增删改查的操作。AST 是一个树形对象,遍历 AST 对象的过程也是一个深度优先遍历的过程。

k0i28资讯网——每日最新资讯28at.com

  • babel-generator负责将 AST 节点,转为代码字符串,同时也可以生成 source-map。

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

插件模块

k0i28资讯网——每日最新资讯28at.com

插件模块包括 plugins、presets。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • plugins丰富的插件,帮助 Babel 成为一个非常成功的转译工具。对 AST 的遍历、转换是 Babel 转译的核心功能,但 Babel 本身并不参与该过程,将这些功能作为插件引入到运行时。具体来说,babel-core 作为核心工具,不提供对 AST 的修改逻辑,通过调用各类插件,实现对 AST 的修改。Babel的插件分为语法插件和转换插件。

k0i28资讯网——每日最新资讯28at.com

语法插件k0i28资讯网——每日最新资讯28at.com

值得注意的是,babel-parser 负责将 JavaScript 代码解析出抽象语法树(AST),它支持全面识别 ESNext/TypeScript/JSX/Flow 等语法,目前由 Babel 团队开发维护,不支持插件化。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

Babel 插件生态中的语法插件,其功能就是作为"开关",配置是否开启 babel-parser 的某些语法转译功能。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

语法插件在 Babel 源码中,以 babel-plugin-syntax 开头。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

举个例子:k0i28资讯网——每日最新资讯28at.com

babel-plugin-syntax-decorators负责开启 babel-parser 对装饰器的语法支持。k0i28资讯网——每日最新资讯28at.com

babel-plugin-syntax-dynamic-import负责开启 babel-parser 对 import 语句的语法支持。k0i28资讯网——每日最新资讯28at.com

babel-plugin-syntax-jsx负责开启 babel-parser 对 jsx 语法的支持。k0i28资讯网——每日最新资讯28at.com

  • 转换插件转换插件就是社区里常说的 Babel 插件,负责转换 AST 节点。在介绍babel-traverse时提到,它负责遍历AST对象,每个AST节点会被访问到,等待转换,转换的部分,由"转换插件"负责。转换插件会提供一个叫做"Visitor"的对象,该对象的 Key 为节点名称,Value 部分提供进入该节点时、离开该节点时的回调函数,在回调函数里,可以对该节点进行一系列操作。"Visitor" 又称为 "访问者"。
// plugin 提供 visitor,在 visitor 中对 AST 节点操作const visitor = {    Program: {        enter() {},        exit() {},    },    CallExpression: {        enter() {},        exit() {},    },    NumberLiteral: {        enter() {},        exit() {},    }};traverse(ast, visitor);

转换插件在Babel源码中,以 babel-plugin-transform 开头。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

举个例子:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

babel-plugin-transform-strict-modek0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

该插件拦截 Program 节点,也就是整个程序的根节点,添加 "use strict"指令。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

visitor 节点值为函数时,是 enter 回调的快捷方式。k0i28资讯网——每日最新资讯28at.com

{    name: "transform-strict-mode",    visitor: {      Program(path) {        const { node } = path;        for (const directive of node.directives) {          if (directive.value.value === "use strict") return;        }        path.unshiftContainer(          "directives",          t.directive(t.directiveLiteral("use strict")),        );      },    },  };}
  • babel-plugin-transform-object-assign

k0i28资讯网——每日最新资讯28at.com

该插件负责拦截函数调用表达式节点 CallExpression,将 Object.assign 转为 extends 写法。k0i28资讯网——每日最新资讯28at.com

{    name: "transform-object-assign",    visitor: {      CallExpression(path, file) {        if (path.get("callee").matchesPattern("Object.assign")) {          path.node.callee = file.addHelper("extends");        }      },    },}
  • PresetsBabel 插件的功能是细粒度的,大部分插件承担了单一功能。而在实际开发过程中,往往需要支持对各类语法的支持。此时,有两种做法:

k0i28资讯网——每日最新资讯28at.com

需要支持哪些特性,就分别引入支持该特性的插件k0i28资讯网——每日最新资讯28at.com

直接引入一个插件集合,涵盖所需的各类插件功能k0i28资讯网——每日最新资讯28at.com

很显然,第一种做法是相对麻烦的。针对第二种做法,Babel提供了插件集 preset。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

preset 在 Babel 源码中,以 babel-preset 开头。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

例如,Babel 已经提供了几种常用的 preset 供开发者使用:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

babel-preset-envk0i28资讯网——每日最新资讯28at.com

babel-preset-reactk0i28资讯网——每日最新资讯28at.com

babel-preset-flowk0i28资讯网——每日最新资讯28at.com

babel-preset-typescriptk0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • 插件运行顺序Babel 配置项中,plugins 和 presets 均以数组的形式配置,执行时有先后顺序。

k0i28资讯网——每日最新资讯28at.com

plugins 在 presets之前运行k0i28资讯网——每日最新资讯28at.com

plugins 按照数组正序执行k0i28资讯网——每日最新资讯28at.com

presets 按照数组倒序执行k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

工具模块

k0i28资讯网——每日最新资讯28at.com

工具模块提供 Babel 相关模块所需的各类工具,以下一一简要介绍:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-corebabel-core 对外提供了 Babel 多项功能的 API,如转译文件、转译代码、创建/获取配置等,在 Babel 官方文档介绍的比较详细,不再赘述。值得注意的是,转译类的 API 均提供了同步和异步版本,如 transformSync/transfomAsync、parseSync/parseAsync。

k0i28资讯网——每日最新资讯28at.com

  • babel-cliBabel 的命令行工具,可以直接转译文件夹/文件,它也提供了很多配置项做其他工作,官方文档介绍的比较详细,感兴趣的同学可以去 Babel 官网查看详细配置。

k0i28资讯网——每日最新资讯28at.com

  • babel-standaloneBabel 对外服务的很多包是基于 node 环境下使用的,babel-standalone 提供了浏览器下转译的方案。babel-standalone 内置了所有 Babel 插件,所以体积还是比较大的,而且在浏览器端转译需要时间,比较适合开发、学习使用,不适合在生产环境使用。举个例子:
<!DOCTYPE html><html>  <head>    <meta charset="utf-8" />    <title>test babel-standalone</title>    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>    <script type="text/babel">      const arr = [1, 2, 3];      console.log(...arr);</script>  </head>  <body></body></html>

在浏览器运行该 html,可以看到,页面结构变成了:k0i28资讯网——每日最新资讯28at.com

<!DOCTYPE html><html>  <head>    <meta charset="utf-8" />    <title>test babel-standalone</title>    <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>    <script type="text/babel">      const arr = [1, 2, 3];      console.log(...arr);</script>    <script>      "use strict";      var _console;      var arr = [1, 2, 3];      (_console = console).log.apply(_console, arr); //# sourceMappingURL=data:application/json;charset=utf-8;base64...</script>  </head>  <body></body></html>
  • babel-node

k0i28资讯网——每日最新资讯28at.com

提供在命令行执行高级语法的环境。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

例如:k0i28资讯网——每日最新资讯28at.com

// index.js 里可以使用高级语法     babel-node -e index.js

index.js 文件以及被其引入的其他文件均可以使用高级语法了。和 babel-cli 不同的是,babel-cli 只负责转换,不在 node 运行时执行;babel-node 会在 node 运行时执行转换,不适合生产环境使用。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-register

k0i28资讯网——每日最新资讯28at.com

在源文件中,引入babel-register,如 index.js:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

index.jsk0i28资讯网——每日最新资讯28at.com

require('babel-register');     require('./run');

run.jsk0i28资讯网——每日最新资讯28at.com

import fs from 'fs';     console.log(fs);

执行 node index 时,run.js 就不需要被转码了。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

babel-register 通过拦截 node require 方法,为 node 运行时引入了 Babel 的转译能力。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-loader

k0i28资讯网——每日最新资讯28at.com

babel-loader 是利用 babel-core 的 API 封装的 webpack loader,用于 webpack 构建过程。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-types

k0i28资讯网——每日最新资讯28at.com

babel-types 是一个非常强大的工具集合,它集成了节点校验、增删改查等功能,是 Babel 核心模块开发、插件开发等场景下不可或缺的工具。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

例如:k0i28资讯网——每日最新资讯28at.com

const t = require('@babel/types');const binaryExpression = t.binaryExpression('+', t.numericLiteral(1), t.numericLiteral(2));
  • babel-template

k0i28资讯网——每日最新资讯28at.com

模板引擎,负责将代码字符串转为 AST 节点对象。k0i28资讯网——每日最新资讯28at.com

import { smart as template } from '@babel/template';    import generate from '@babel/generator';    import * as t from '@babel/types';    const buildRequire = template(      var %%importName%% = require(%%source%%);    );    const ast = buildRequire({        importName: t.identifier('myModule'),        source: t.stringLiteral("my-module"),    });    const code = generate(ast).code    console.log(code)

        运行结果:k0i28资讯网——每日最新资讯28at.com

var myModule = require("my-module");
  • babel-code-frame

k0i28资讯网——每日最新资讯28at.com

负责打印出错的代码位置,例如:k0i28资讯网——每日最新资讯28at.com

const { codeFrameColumns } = require('@babel/code-frame');const testCode = `class Run {    constructor() {}}`;const location = {    start: {        line: 2,        column: 2,    }};const result = codeFrameColumns(testCode, location);console.log(result);
1 | class Run {> 2 |     constructor() {}    |  ^  3 | }  4 |
  • babel-highlight

k0i28资讯网——每日最新资讯28at.com

向控制台输出有颜色的代码片段。该工具可以识别 JavaScript 中的操作符号、标识符、保留字等类型的词法单元,并在终端环境下显示不同的颜色。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

运行时相关模块

k0i28资讯网——每日最新资讯28at.com

Babel 配合其插件可以对静态代码进行转译,但有一些遗漏点:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • 对于运行时涉及的一些高版本 API,并没有提供兼容目标环境的 Polyfill。
  • 转译产物代码可能有些臃肿。

k0i28资讯网——每日最新资讯28at.com

为此,运行时模块(runtime)关注的是转译产物的运行时环境,对运行时提供 API polyfill、代码优化等,该模块涉及几个子包:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-preset-env
  • babel-plugin-transform-runtime
  • babel-runtime
  • babel-runtime-corejs2/3
  • core-js

k0i28资讯网——每日最新资讯28at.com

接下来以案例解释 runtime 模块的作用。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

源码文件 index.js 的内容:k0i28资讯网——每日最新资讯28at.com

const a = 1; // const 为语法部分class Base {} // class 为语法部分new Promise() // Promise 为 API 部分

这段源码包含了语法和 API 部分:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • const、class 为语法部分
  • Promise 为 API 部分

k0i28资讯网——每日最新资讯28at.com

如果希望这段源码转为 ES5 版本,使构建产物可以运行在不支持 ES6 和 Promise 的环境里,该怎么做呢?k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

用 babel 命令行执行转译,其中源文件为 index.js,转译产物文件为 index-compiled.js。k0i28资讯网——每日最新资讯28at.com

npx babel index.js --out-file index-compiled.js

需要配置.babelrc 帮助 Babel 完成语法和 API 部分的转译:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

.babelrc:k0i28资讯网——每日最新资讯28at.com

{    "presets": [        [             "@babel/preset-env"        ]    ],    "plugins": [        [            "@babel/plugin-transform-runtime",            {                "corejs": 3            }        ]    ]}

简要解释下该配置的原理:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-preset-env 可以完成语法部分转译,即 const 转译为var但构建产物中,有些辅助代码如 _classCallCheck 是以硬编码的形式直接写入转译产物的:
"use strict";    function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }    var a = 1;    var Base = function Base() {        _classCallCheck(this, Base);    };    new Promise();

这样的后果就是构建产物比较臃肿。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • babel-plugin-transform-runtime 可以将上述 _classCallCheck 置于通用包中,以引用的形式写入转译产物:
"use strict";    var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");    var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));    var a = 1;    var Base = function Base() {        (0, _classCallCheck2["default"])(this, Base);    };    new Promise();
  • babel-plugin-transform-runtime 的配置参数 corejs 用于转译 API 部分,如 Promsie
"use strict";    var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault");    var _promise = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/promise"));    var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/classCallCheck"));    var a = 1;    var Base = function Base() {        (0, _classCallCheck2["default"])(this, Base);    };    new _promise"default";

Babel 转译过程的运行时优化是一个繁琐的过程,为此将单独用一章讲解运行时优化,感兴趣的同学可以直接阅读 "Babel Runtime" 章节详细了解。k0i28资讯网——每日最新资讯28at.com

三、标准化

Babel 生态涉及的一些标准化组织。无论是 JavaScript、HTML、DOM、URL 等领域,均需要统一的标准,才能在不同的运行环境下有统一的表现。Babel 转译也需要遵循这些标准,包括 ECMAScript、web标准等。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

ECMAScript

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

JavaScript诞生

1995 年,JavaScript 的第一个版本发布。用时间线的方式描述 JavaScript 的诞生过程会更清晰: k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

ECMAScript发布

1996 年,微软模仿 JavaScript 实现了 JScript 并内置在 IE3.0,随后,Netscape 公司着手推动 JavaScript 标准化。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

这里涉及几个组织:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • Ecma International

k0i28资讯网——每日最新资讯28at.com

Ecma International 是一家国际性会员制度的信息和电信标准组织。1994年之前,名为欧洲计算机制造商协会(European Computer Manufacturers Association)。因为计算机的国际化,组织的标准牵涉到很多其他国家,因此组织决定改名表明其国际性。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

Ecma International 的任务包括与有关组织合作开发通信技术和消费电子标准、鼓励准确的标准落实、和标准文件与相关技术报告的出版。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

Ecma International 负责多个国际标准的制定:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • CD-ROM 格式(之后被国际标准化组织批准为ISO 9660)
  • C# 语言规范
  • C++/CLI 语言规范
  • 通用语言架构(CLI)
  • Eiffel 语言
  • 电子产品环境化设计要素
  • Universal 3D 标准
  • OOXML
  • Dart 语言规范
  • ECMAScript 语言规范(以 JavaScript 为基础)ECMA-262其中就包括 JavaScript 标准语言规范 ECMAScript。cma International 拥有 ECMAScript 的商标。
  • ECMA TC39

k0i28资讯网——每日最新资讯28at.com

「TC39」全称「Technical Committee 39」译为「第 39 号技术委员会」,是 Ecma International 组织架构中的一部分。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

TC39 负责迭代和发展 ECMAScript,它的成员由各个主流浏览器厂商的代表组成,通常每年召开约 6 次会议来讨论未决提案的进展情况,会议的每一项决议必须得到大部分人的赞同,并且没有人强烈反对才可以通过。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

TC39 负责:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

维护和更新 ECMAScript 语言标准k0i28资讯网——每日最新资讯28at.com

识别、开发、维护 ECMAScript 的扩展功能库k0i28资讯网——每日最新资讯28at.com

开发测试套件k0i28资讯网——每日最新资讯28at.com

为 ISO/IEC JTC 1 提供标准k0i28资讯网——每日最新资讯28at.com

评估和考虑新添加的标准k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • ISO

k0i28资讯网——每日最新资讯28at.com

国际标准化组织(英语: International Organization for Standardization,简称: ISO)成立于 1947 年 2 月 23 日,制定全世界工商业国际标准的国际标准建立机构。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

ISO 的国际标准以数字表示,例如: "ISO 11180:1993" 的 "11180" 是标准号码,而 "1993" 是出版年份。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

ISO/IEC JTC 1 是国际标准化组织和国际电工委员会联合技术委员会。其目的是开发、维护和促进信息技术以及信息和通信技术领域的标准。JTC 1 负责了许多关键的 IT 标准,从 MPEG 视频格式到 C++ 编程语言。k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

  • ECMAScript 发展过程中的关键节点

图片图片k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

ECMAScript 各版本

ECMAScript 经历了多个版本,每个版本有自己的特点,简单列举如下: k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

ECMAScript 迭代过程

一个 ECMAScript 标准的制作过程,包含了 Stage 0 到 Stage 4 共 5 个阶段,每个阶段提交至下一阶段都需要 TC39 审批通过。k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

特性进入 Stage-4 后,才有可能被加入标准中,还需要 ECMA General Assembly 表决通过才能进入下一次的 ECMAScript 标准中。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

如何阅读 ECMAScript

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

ECMAScript 文档结构

ECMAScript 的规格,可以在 ECMA 国际标准组织的官方网站免费下载和在线阅读。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

查看ECMAScript 不同版本的地址:https://ecma-international.org/publications-and-standards/standards/ecma-262/。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

截至 2023年底,已发布的版本如下:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • ECMA-262 5.1 edition, June 2011

(https://262.ecma-international.org/5.1/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 6th edition, June 2015

(https://262.ecma-international.org/6.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 7th edition, June 2016

(https://262.ecma-international.org/7.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 8th edition, June 2017

(https://262.ecma-international.org/8.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 9th edition, June 2018

(https://262.ecma-international.org/9.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 10th edition, June 2019

(https://262.ecma-international.org/10.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 11th edition, June 2020

(https://262.ecma-international.org/11.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 12th edition, June 2021

(https://262.ecma-international.org/12.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 13th edition, June 2022

(https://262.ecma-international.org/13.0/index.html)k0i28资讯网——每日最新资讯28at.com

  • ECMA-262, 14th edition, June 2023

(https://262.ecma-international.org/14.0/index.html)k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

每个版本有独立的网址,格式为: https://262.ecma-international.org/{version}/,比如 ECMAScript 14.0 版本的网址为 https://262.ecma-international.org/14.0/。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

从章节数量上,ECMAScript 6.0、ECMAScript 7.0 有 26 章,之后的版本有 27-29 章,虽然章节数量不同,规格章节的分布是保持一定规律的,以 ECMAScript 11.0 版本为例:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • Introduction: 介绍部分

k0i28资讯网——每日最新资讯28at.com

该章节简要描述了: JavaScript 和 ECMAScript 的发展历史、不同 ECMAScript 规格的主要更新内容。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • 第 1 章到第 3 章: 描述了规格文件本身,而非语言

第 1 章用一句话描述了该规格的描述范围。k0i28资讯网——每日最新资讯28at.com

第 2 章描述了基于规格的"实现"的一致性要求:k0i28资讯网——每日最新资讯28at.com

"实现"必须支持规格中描述的所有类型、值、对象、属性、函数以及程序的语法和语义k0i28资讯网——每日最新资讯28at.com

"实现"必须按照 Unicode 标准和 ISO/IEC 10646 的最新版本处理文本输入k0i28资讯网——每日最新资讯28at.com

"实现"如果提供了应用程序编程接口(API),那么该 API 需要适应不同的人文语言和国家差异,且必须实现最新版本的 ECMA-402 所定义的与本规范相兼容的接口k0i28资讯网——每日最新资讯28at.com

"实现"可以支持该规格中没有提及的类型、值、对象、属性、函数、正则表达式语法以及其他编程写法k0i28资讯网——每日最新资讯28at.com

"实现"不能实现该规格中禁止的写法k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • 第 3 章描述了该规格的一些参考资料:
  • ISO/IEC 10646
  • ECMA-402
  • EMCA-404 JSON 数据交换格式规范
  • 第 4 章: 对这门语言总体设计的描述。
  • 第 5 章到第 8 章: 语言宏观层面的描述。
  • 第 6 章介绍数据类型。
  • 第 7 章介绍语言内部用到的抽象操作。
  • 第 8 章介绍代码如何运行。
  • 第 9 章到第 27 章: 介绍具体的语法。

k0i28资讯网——每日最新资讯28at.com

一般而言,除非写编译器,开发者无需阅读 ECMAScript 的规格,规格的内容非常多,如无必要也无需通读。只是在遇到一些奇怪的问题时,阅读官方规格,是最稳妥的办法。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

通过阅读规格解决一些问题k0i28资讯网——每日最新资讯28at.com

(以ECMAScript 11.0为例)k0i28资讯网——每日最新资讯28at.com

  • 识别关键词和保留字,并高亮

k0i28资讯网——每日最新资讯28at.com

Babel 工具集中的 babel-highlight,可以实现在终端对代码块中的目标字符单元显示不同的颜色。这里需要识别不同字符单元的类型,如关键字、保留字、标识符、数字、字符串等。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

标识符、数字、字符串都很好理解和识别,但哪些字符应该被识别为关键字、保留字,而不是标识符呢?k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

此时可以阅读 ECMAScript 规格了,ECMAScript 11.0 规格的 11.6.2 节介绍了关键词和保留字列表。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

关键词(keywords)关键词首先是标识符,同时有语义,包括 if、while、async、await...,个别关键词是可以用作变量名的。k0i28资讯网——每日最新资讯28at.com

保留字(reserved word)保留字首先是标识符,但不能用作变量名。部分关键词是保留字,但部分不是: if、while是保留字;await只有在 async方法和模块中才是保留字;async不是保留字,它可以作为普通的变量名使用。k0i28资讯网——每日最新资讯28at.com

保留字列表k0i28资讯网——每日最新资讯28at.com

awaitbreakcasecatchclassconstcontinuedebuggerdefaultdeletedoelseenumexportextendsfalsefinallyforfunctionifimportininstanceofnewnullreturnsuperswitchthisthrowtruetrytypeofvarvoidwhilewithyield

读完上述规格,也就知道哪些字符单元是需要识别为保留字与关键词,并高亮的了。k0i28资讯网——每日最新资讯28at.com

  • 识别全局对象,并高亮

k0i28资讯网——每日最新资讯28at.com

继续使用 babel-highlight 实现代码块中的全局对象高亮,那么,我们需要知道哪些是规格中描述的全局变量。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

规格的 18 章介绍了全局对象,通过该章的描述,可以知道: k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

全局属性全局属性有: globalThis、Infinity、NaN、undefined。k0i28资讯网——每日最新资讯28at.com

全局方法k0i28资讯网——每日最新资讯28at.com

全局方法有: eval(x)、isFinite、isNaN、parseFloat、parseInt、decodeURIComponent、encodeURIComponent 等。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • 全局构造函数

全局的构造函数有: k0i28资讯网——每日最新资讯28at.com

ArrayArrayBufferBigIntBigInt64ArrayBigUnit64ArrayBooleanDataViewDateErrorEvalErrorFloat32ArrayFloat64ArrayFunctionInt8ArrayInt16ArrayInt32ArrayMapNumberObjectPromiseProxyRangeErrorReferenceErrorRegExpSetSharedArrayBufferStringSymbolSyntaxErrorTypeErrorUint8ArrayUint8ClampedArrayUint16ArrayUint32ArrayURIErrorWeakMapWeakSet

其他的全局属性Atomics、JSON、Math、Reflect。很显然,当字符单元的名称是上述名称中的一员时,我们可以对其进行高亮处理了(若上下文中无重新定义的同名变量)。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • 自定义 Error

k0i28资讯网——每日最新资讯28at.com

babel-loader 自身维护了私有的 LoaderError 对象,该对象继承自原生 Error 类,并且订制了部分实例属性。代码如下: k0i28资讯网——每日最新资讯28at.com

class LoaderError extends Error {    constructor(err) {        super();        const { name, message, codeFrame, hideStack } = format(err);        this.name = "BabelLoaderError";        this.message = ${name ? ${name}: ` : ""}${message}/n/n${codeFrame}/n`;        this.hideStack = hideStack;        Error.captureStackTrace(this, this.constructor);    }}

可以看到,babel-loader 自定义了错误实例的 name、message、hideStack 属性,那么,问题是,原生的 Error 类有哪些属性和方法,哪些是开发者可以自定义的呢?k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

规格的 19.5 章节,详细介绍了 Error 的各类规范:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

Error 作为函数被调用时(Error(...)),表现和 new Error(...) 一致,均会创建并返回 Error 的新实例k0i28资讯网——每日最新资讯28at.com

Error 可以被继承,比如通过 extends 的方式,子类必须提供 constructor 方法,且该方法内必须提供 super() 调用k0i28资讯网——每日最新资讯28at.com

Error 构造函数必须有 prototype 属性k0i28资讯网——每日最新资讯28at.com

Error.prototype 属性需有以下属性:k0i28资讯网——每日最新资讯28at.com

Error.prototype.constructor: 指向构造函数k0i28资讯网——每日最新资讯28at.com

Error.prototype.message: 描述错误信息,默认是空字符串k0i28资讯网——每日最新资讯28at.com

Error.prototype.name: 描述错误名称,默认值是 Errork0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

从 LoaderError 的源码可以看到,LoaderError 做了以下几件事情:k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

  • LoaderError 继承自 Error
  • 实例自定义了 name、message 属性,明确 babel-loader 的信息
  • 实例自定义的 hideStack 属性是非标准属性,用于 babel-loader 内部

k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

web标准

k0i28资讯网——每日最新资讯28at.com

是在解决 API Polyfil 的时候,Babel 配合使用的 core-js 除了提供 ECMAScript 标准下的 JavaScript API 实现,也提供了 DOM/URL 等实现。而 DOM/URL 所属的 web 标准,由 W3C/WHATWG 制定。k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

经过多年发展,WHATWG 和 W3C 目前是合作关系,其中,WHATWG 维护 HTML 和 DOM 标准,W3C 使用 WHATWG 存储库中的 HTML 和 DOM 标准描述,W3C 在 HTML 部分的工作集中在 XHTML/XML 上。k0i28资讯网——每日最新资讯28at.com

图片图片k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

四、总结

本文介绍了 Babel 的概述/微内核架构/ECMAScript标准化方面的设计思想和部分实现原理。k0i28资讯网——每日最新资讯28at.com

k0i28资讯网——每日最新资讯28at.com

上述内容其实在很早之前就已经成型了,笔者也查看了Babel最近的迭代内容,发现并没有太大的变化。至于代码转译领域,目前是Babel还是其他工具哪个更有优势,不在本文的讨论范围内。除了比较社区哪些工具更好而言,“Babel的设计思路、其与标准规范是怎么配合的”等也是很值得学习的地方,也是这篇文章的产生背景。k0i28资讯网——每日最新资讯28at.com

本文链接:http://www.28at.com/showinfo-26-112790-0.html深入理解 Babel - 微内核架构与 ECMAScript 标准化

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: DevOps流程最全详解(7大流程步骤图解)

下一篇: 记一次线程池使用不当触发死锁导致RocketMQ消费停滞

标签:
  • 热门焦点
Top