前言

前言

随着 ECMA 标准的不断更新,从较早的 ECMA3 到 ECMA5 的重大升级,以及时至今日的 ECMA13(2022) 版本,伴随着的是浏览器厂商在 JavaScript
基础语法实现上的不断进步,但不可避免的是在版本碎片化的背景下,我们需要一些工具去抹平版本差异,比如:padStart 语法在 Chrome 57 版本及以后才兼容。
alt text
那如果需要在 57 之前的版本中运行箭头函数,通常的做法是使用 Babel 。Babel 能够根据不同的浏览器版本,判断出需要哪些 polyfill ,并按需加载,转译后的代码如下:

1
2
3
4
5
require("core-js/modules/es.string.pad-start");

var arrow = function arrow() {
return "Name: ".concat(cat).padStart(2);
};

通常 Babel 结合 CoreJs 的配置如下:

1
2
3
4
5
6
7
8
module.exports = {
presets: [
['@babel/preset-env', {
useBuiltIns: 'usage',
corejs: 3 // 表示使用 CoreJs 3 版本的库
}]
],
};

也正是在这样的契机下,在使用 Babel 的过程中,注意到了底层的依赖 CoreJs 库,CoreJs 源码使用 ECMA3 的语法,实现 ECMA 更高阶版本的语法,因此萌发了写这个系列的文章《从 CoreJs 源码学习 JavaScript 语法》。
例如上文提到的padStart方法,在 CoreJs 中实现如下:

// `String.prototype.{ padStart, padEnd }` methods implementation
var createMethod = function (IS_END) {
  return function ($this, maxLength, fillString) {
    var S = toString(requireObjectCoercible($this));
    var intMaxLength = toLength(maxLength);
    var stringLength = S.length;
    var fillStr = fillString === undefined ? ' ' : toString(fillString);
    var fillLen, stringFiller;
    if (intMaxLength <= stringLength || fillStr == '') return S;
    fillLen = intMaxLength - stringLength;
    stringFiller = repeat(fillStr, ceil(fillLen / fillStr.length));
    if (stringFiller.length > fillLen) stringFiller = stringSlice(stringFiller, 0, fillLen);
    return IS_END ? S + stringFiller : stringFiller + S;
  };
};

通过学习 CoreJs 源码,我们可以有以下收获:

  • 了解 JavaScript 语法转译的过程;
  • 掌握 ECMA 多个版本的语法特性及其具体实现;
  • 提升 JavaScript 写法的灵活性;

整体的介绍顺序如下:

  • 工程目录结构;
  • Babel + CoreJs 是如何把 ES5+ 语法转换为当前目标浏览器能运行的版本语法;
  • 按照数据结构维度,介绍其中有特色的实现;

对于什么是 CoreJs,作者的介绍如下:

  • 它是JavaScript标准库的 polyfill,它支持
    • 最新的 ECMAScript 标准
    • ECMAScript 标准库提案
    • 一些 WHATWG / W3C 标准(跨平台或者 ECMAScript 相关)
  • 它最大限度的模块化:你能仅仅加载你想要使用的功能
  • 它能够不污染全局命名空间
  • 它和 babel紧密集成 优化core-js的导入