ECMAScript 基于多种原始技术,最著名的是 JavaScript (Netscape) 和 JScript (Microsoft)。截止2022年,正式标准一共发布12次,es2020草案撰写中。
至此之后,Ecma TC39 采用年度发布节奏
Object.values
、Object.entries
和 Object.getOwnPropertyDescriptors
;Array.prototype
上的 flat
和 flatMap
用于扁平化数组;Object.fromEntries
用于直接将 Object.entries
的返回值转换为新的 Object
;String.prototype
上的 trimStart
和 trimEnd
效果更好;String.prototype.trimLLeft
和 trimRight
内置函数的命名替代品。U+2028 (LINE SEPARATOR)
和 U+2029 (PARAGRAPH SEPARATOR)
与 JSON 对齐。Array.prototype.sort
是稳定的排序,matchAll
方法,为全局正则表达式生成的所有匹配对象生成迭代器;import()
,一种使用动态说明符异步导入模块的语法;BigInt
,一种用于处理任意精度整数的新数字原语;Promise.allSettled
,一个新的不会短路的 Promise 组合器;globalThis
,一种访问全局 this 值的通用方式;* as ns from 'module'
语法在模块中使用;for-in
枚举顺序的标准化;import.meta
,模块中可用的主机填充对象,可能包含有关模块的上下文信息;replaceAll
方法;Promise.any
,一个 Promise 组合器,当输入值被满足时短路;AggregateError
,一种新的 Error 类型,用于同时表示多个错误;??=
, &&=
, ||=
);WeakRef
,用于引用目标对象而不将其从垃圾收集中保留;FinalizationRegistry
,用于管理在目标对象被垃圾收集时执行的清理操作的注册和注销;1_000
);Array.prototype.sort
变得更加精确,减少了导致实现定义的排序顺序的案例数量。Babel 是一个工具链,主要用于将采用 ECMAScript 2015+ 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。概念内容可以参考官网或这里。
Babel 的预设(preset)可以被看作是一组 Babel 插件或 options
配置的可共享模块。
官方提供的预设
名称 | 说明 |
---|---|
@babel/preset-env | 编译 ES2015+ 语法 |
@babel/preset-typescript | 编译 Typescript 语法 |
@babel/preset-react | 编译 React 语法 |
@babel/preset-flow | 编译 Flow 语法 |
这里需要说明的是:babel-preset-env 具有不同的版本,包含的规范(插件)也不一致
示例:v7.15.0 包含了 es2020 相关插件;v7.4.0 并不包含 es2020 相关插件。
{
"@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
"@babel/plugin-syntax-optional-chaining": "^7.8.3"
}
所以,即便同样指定 babel 的 presets 为 babel-preset-env
,也需要查看其版本,确定指定版本中是否包含相应的新规范内容插件。
presets: [
"@babel/preset-env",
],
默认情况下,Babel 期望插件在其名称中具有 babel-plugin-
或 babel-preset-
前缀。为了避免重复,Babel 有一个名称规范化阶段会在加载项目时自动添加这些前缀。
规则 | 输入 | Normalized |
---|---|---|
绝对路径原封不动地通过 | “/dir/plugin.js” | “/dir/plugin.js” |
以 ./ 开头的相对路径原封不动 | “./dir/plugin.js” | “./dir/plugin.js” |
以 module: 为前缀的标识符都将删除前缀 | “module:foo” | “foo” |
plugin-/preset- 将在任何没有它作为前缀的@babel-scoped 包的开头注入 | “@babel/mod” | “@babel/plugin-mod” |
babel-plugin-/babel-preset- 将作为前缀注入任何没有它作为前缀的无作用域包 | “mod” | “babel-plugin-mod” |
babel-plugin-/babel-preset- 将作为前缀注入任何名称中没有它的@-scoped 包 | “@scope/mod” | “@scope/babel-plugin-mod” |
如果只给出@-scope 名称,babel-plugin/babel-preset 将作为包名称注入 | “@scope” | “@scope/babel-plugin” |
官方地址:https://babeljs.io/docs/en/options#name-normalization
示例:es2020
@babel/plugin-proposal-nullish-coalescing-operator @babel/plugin-proposal-optional-chaining @babel/plugin-syntax-import-meta
官方地址:https://babeljs.io/docs/en/plugins-list
vue2 中使用 es6+,需要搞懂 vue cli 同 babel 结合的方式,然后增加相关插件。
一个默认的 Vue CLI 项目会使用 @vue/babel-preset-app(使用的默认 Babel 预设),它通过 @babel/preset-env
和 browserslist
配置来决定项目需要的 polyfill。
package.json
文件里的browserslist
字段 (或一个单独的.browserslistrc
文件),指定了项目的目标浏览器的范围。这个值会被 @babel/preset-env 和 Autoprefixer 用来确定需要转译的 JavaScript 特性和需要添加的 CSS 浏览器前缀。
module.exports = {
presets: [
'@vue/app'
]
}
name 规范化:@vue/app
实际对应的是 @vue/babel-preset-app
@vue/babel-preset-app 包括的插件:
{
"@babel/preset-env": "^7.12.16",
"babel-plugin-dynamic-import-node": "^2.3.3",
"@babel/plugin-proposal-class-properties": "^7.12.13",
"@babel/plugin-proposal-decorators": "^7.12.13",
"@vue/babel-plugin-jsx": "^1.0.3",
"@vue/babel-preset-jsx": "^1.1.2"
}
注意:@vue/babel-preset-app
版本不同,对应的 @babel/preset-env
不同,因此包含的默认规则必然不同。
以 可选链操作符 ?.
为示例
const obj = {}
obj?.foo?.()
第一步:确定“可选链操作符”为 ES2020 新增特性;
第二步:获取当前工程中 @vue/babel-preset-app
版本,以便获取其依赖项 @babel/preset-env
版本
第三步:根据@babel/preset-env
版本,来确定是否包含 ES2020 特性;
第四步:如果已包含,则工程中可以使用;跳过后续所有步骤;
第五步:如果不包含,或去对应 plugin,列表地址
第六步:项目中按照相关依赖,并增加 plugin 配置
$ pnpm install --save-dev @babel/plugin-proposal-optional-chaining
babel.config.js
module.exports = {
presets: [
'@vue/app'
],
plugins: [
'@babel/plugin-proposal-optional-chaining'
]
}
template 模板中支持(vue.config.js中增加相关配置)
chainWebpack: (config) => {
config.module
.rule('vue')
.use('vue-loader')
.tap(options => {
options.compiler = require('vue-template-babel-compiler')
return options
})
}