babel插件

2022/10/8 babel

# ES3

1.@babel/plugin-transform-reserved-words 保留关键字转换插件

image-20221008140213307

输入

var abstract = 1;
var x = abstract + 1;

输出

var _abstract = 1;
var x = _abstract + 1;

2.@babel/plugin-transform-member-expression-literals 保留关键字对象转换

输入

obj.foo = "isValid";

obj.const = "isKeyword";
obj["var"] = "isKeyword";

输出

obj.foo = "isValid";

obj["const"] = "isKeyword";
obj["var"] = "isKeyword";

# ES5

@babel/plugin-transform-property-mutators 访问设置器转换

输入

var foo = {
  get bar() {
    return this._bar;
  },
  set bar(value) {
    this._bar = value;
  },
};

输出

var foo = Object.defineProperties(
  {},
  {
    bar: {
      get: function() {
        return this._bar;
      },
      set: function(value) {
        this._bar = value;
      },
      configurable: true,
      enumerable: true,
    },
  }
);

# ES2015

1.@babel/plugin-transform-unicode-regex 转换正则为unicode码

输入

var string = 'foobar';
var match = string.match(/foo(.)bar/u);

输出

var string = 'foobar';
var match = string.match(
  /foo((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))bar/
);

2.@babel/plugin-transform-unicode-escapes 编译unicode编码为es5

输入

var \u{1d49c} = "\u{Babe1}";
console.log(\u{1d49c});

输出

var _ud835_udc9c = '\udaaa\udfe1';
console.log(_ud835_udc9c);

3.@babel/plugin-transform-typeof-symbol 转换typeof symbol

输入

typeof Symbol() === 'symbol';

输出

function _typeof(obj) {
  '@babel/helpers - typeof';
  return (
    (_typeof =
      'function' == typeof Symbol && 'symbol' == typeof Symbol.iterator
        ? function (obj) {
            return typeof obj;
          }
        : function (obj) {
            return obj &&
              'function' == typeof Symbol &&
              obj.constructor === Symbol &&
              obj !== Symbol.prototype
              ? 'symbol'
              : typeof obj;
          }),
    _typeof(obj)
  );
}

_typeof(Symbol()) === 'symbol';

4.@babel/plugin-transform-template-literals 模板语法转换

输入

`foo${bar}${c}`;

输出

"foo".concat(bar).concat(c);

5.@babel/plugin-transform-sticky-regex 正则表达式转换

输入

const a = /o+/y;

输出

const a = new RegExp("o+", "y");

6.@babel/plugin-transform-spread 扩展语法转换

输入

var a = ['a', 'b', 'c'];

var b = [...a, 'foo', 'bar'];

var c = foo(...a);

输出

var a = ['a', 'b', 'c'];
var b = [].concat(a, ['foo', 'bar']);
var c = foo.apply(void 0, a);

7.@babel/plugin-transform-shorthand-properties 简写转换

输入

var o = { a, b, c };

var cat = {
  getName() {
    return this.name;
  },
};

输出

var o = {
  a: a,
  b: b,
  c: c
};
var cat = {
  getName: function () {
    return this.name;
  }
};

8.@babel/plugin-transform-parameters 函数参数转换

  • 默认参数
  • 解构参数
  • 剩余参数

输入

function test(x = 'hello', { a, b }, ...args) {
  console.log(x, a, b, args);
}

输出

function test() {
  let x = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'hello';
  let {
    a,
    b
  } = arguments.length > 1 ? arguments[1] : undefined;

  for (var _len = arguments.length, args = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
    args[_key - 2] = arguments[_key];
  }

  console.log(x, a, b, args);
}

9.@babel/plugin-transform-object-super 对象父节点方法转换

输入

let obj = {
  say() {
    return 'Hello';
  },
};

let obj2 = {
  say() {
    return super.say() + 'World!';
  },
};

输出

var _obj;

function _get() { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get.bind(); } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(arguments.length < 3 ? target : receiver); } return desc.value; }; } return _get.apply(this, arguments); }

function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

let obj = {
  say() {
    return 'Hello';
  }

};
let obj2 = _obj = {
  say() {
    return _get(_getPrototypeOf(_obj), "say", this).call(this) + 'World!';
  }

};

10.@babel/plugin-transform-new-target new target转换

输入

function Foo() {
  console.log(new.target);
}

输出

function Foo() {
  console.log(this instanceof Foo ? this.constructor : void 0);
}

11.@babel/plugin-transform-literals 字面量转换

输入

var b = 0b11; // 二进制字面量11
var o = 0o7; // 八进制字面量7
const u = 'Hello\u{000A}\u{0009}!'; // unicode字面量

输出

var b = 3; // 二进制字面量11
var o = 7; // 八进制字面量7
const u = "Hello\n\t!"; // unicode字面量

11.@babel/plugin-transform-instanceof instanceof转换

输入

foo instanceof Bar;

输出

function _instanceof(left, right) {
  if (
    right != null &&
    typeof Symbol !== 'undefined' &&
    right[Symbol.hasInstance]
  ) {
    return !!right[Symbol.hasInstance](left);
  } else {
    return left instanceof right;
  }
}

_instanceof(foo, Bar);

12.@babel/plugin-transform-function-name function name转换

输入

let number = (x) => x;

输出

let number = x => x;

13.@babel/plugin-transform-for-of for of转换

输入

for (var i of foo) {
}

输出

function _createForOfIteratorHelper(o, allowArrayLike) {
  var it =
    (typeof Symbol !== 'undefined' && o[Symbol.iterator]) || o['@@iterator'];
  if (!it) {
    if (
      Array.isArray(o) ||
      (it = _unsupportedIterableToArray(o)) ||
      (allowArrayLike && o && typeof o.length === 'number')
    ) {
      if (it) o = it;
      var i = 0;
      var F = function () {};
      return {
        s: F,
        n: function () {
          if (i >= o.length) return { done: true };
          return { done: false, value: o[i++] };
        },
        e: function (e) {
          throw e;
        },
        f: F,
      };
    }
    throw new TypeError(
      'Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.'
    );
  }
  var normalCompletion = true,
    didErr = false,
    err;
  return {
    s: function () {
      it = it.call(o);
    },
    n: function () {
      var step = it.next();
      normalCompletion = step.done;
      return step;
    },
    e: function (e) {
      didErr = true;
      err = e;
    },
    f: function () {
      try {
        if (!normalCompletion && it.return != null) it.return();
      } finally {
        if (didErr) throw err;
      }
    },
  };
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === 'string') return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === 'Object' && o.constructor) n = o.constructor.name;
  if (n === 'Map' || n === 'Set') return Array.from(o);
  if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
    return _arrayLikeToArray(o, minLen);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;
  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  return arr2;
}

var _iterator = _createForOfIteratorHelper(foo),
  _step;

try {
  for (_iterator.s(); !(_step = _iterator.n()).done; ) {
    var i = _step.value;
  }
} catch (err) {
  _iterator.e(err);
} finally {
  _iterator.f();
}

14.@babel/plugin-transform-duplicate-keys 重复key的覆盖

输入

var x = { a: 5, a: 6 };
var y = {
  get a() {},
  set a(x) {},
  a: 3,
};

输出

var x = {
  a: 5,
  ["a"]: 6
};
var y = {
  get a() {},

  set a(x) {},

  ["a"]: 3
};

15.@babel/plugin-transform-destructuring

输入

let { x, y } = obj;

let [a, b, ...rest] = arr;

输出

function _toArray(arr) {
  return (
    _arrayWithHoles(arr) ||
    _iterableToArray(arr) ||
    _unsupportedIterableToArray(arr) ||
    _nonIterableRest()
  );
}

function _nonIterableRest() {
  throw new TypeError(
    'Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.'
  );
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === 'string') return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === 'Object' && o.constructor) n = o.constructor.name;
  if (n === 'Map' || n === 'Set') return Array.from(o);
  if (n === 'Arguments' || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))
    return _arrayLikeToArray(o, minLen);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;
  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
  return arr2;
}

function _iterableToArray(iter) {
  if (
    (typeof Symbol !== 'undefined' && iter[Symbol.iterator] != null) ||
    iter['@@iterator'] != null
  )
    return Array.from(iter);
}

function _arrayWithHoles(arr) {
  if (Array.isArray(arr)) return arr;
}

let _obj = obj,
  x = _obj.x,
  y = _obj.y;

let _arr = arr,
  _arr2 = _toArray(_arr),
  a = _arr2[0],
  b = _arr2[1],
  rest = _arr2.slice(2);

16.@babel/plugin-transform-computed-properties 计算属性

输入

var obj = {
  ['x' + foo]: 'heh',
  ['y' + bar]: 'noo',
  foo: 'foo',
  bar: 'bar',
};

输出

var _obj;

function _defineProperty(obj, key, value) {
  if (key in obj) {
    Object.defineProperty(obj, key, {
      value: value,
      enumerable: true,
      configurable: true,
      writable: true,
    });
  } else {
    obj[key] = value;
  }
  return obj;
}

var obj =
  ((_obj = {}),
  _defineProperty(_obj, 'x' + foo, 'heh'),
  _defineProperty(_obj, 'y' + bar, 'noo'),
  _defineProperty(_obj, 'foo', 'foo'),
  _defineProperty(_obj, 'bar', 'bar'),
  _obj);

17.@babel/plugin-transform-classes classes转换

输入

class Test {
  constructor(name) {
    this.name = name;
  }

  logger() {
    console.log('Hello', this.name);
  }
}

输出

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function');
  }
}

function _defineProperties(target, props) {
  for (var i = 0; i < props.length; i++) {
    var descriptor = props[i];
    descriptor.enumerable = descriptor.enumerable || false;
    descriptor.configurable = true;
    if ('value' in descriptor) descriptor.writable = true;
    Object.defineProperty(target, descriptor.key, descriptor);
  }
}

function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  Object.defineProperty(Constructor, 'prototype', { writable: false });
  return Constructor;
}

let Test = /*#__PURE__*/ (function () {
  function Test(name) {
    _classCallCheck(this, Test);

    this.name = name;
  }

  _createClass(Test, [
    {
      key: 'logger',
      value: function logger() {
        console.log('Hello', this.name);
      },
    },
  ]);

  return Test;
})();

18.@babel/plugin-transform-block-scoping 块级范围

输入

{
  let a = 3;
}

let a = 3;

输出

{
  var _a = 3;
}
var a = 3;

19.@babel/plugin-transform-arrow-functions 箭头函数

输入

var a = () => {};
var a = (b) => b;

const double = [1, 2, 3].map((num) => num * 2);
console.log(double); // [2,4,6]

var bob = {
  _name: 'Bob',
  _friends: ['Sally', 'Tom'],
  printFriends() {
    this._friends.forEach((f) => console.log(this._name + ' knows ' + f));
  },
};
console.log(bob.printFriends());

输出

var a = function () {};

var a = function (b) {
  return b;
};

const double = [1, 2, 3].map(function (num) {
  return num * 2;
});
console.log(double); // [2,4,6]

var bob = {
  _name: 'Bob',
  _friends: ['Sally', 'Tom'],

  printFriends() {
    var _this = this;

    this._friends.forEach(function (f) {
      return console.log(_this._name + ' knows ' + f);
    });
  }

};
console.log(bob.printFriends());

# ES2016

1.@babel/plugin-transform-exponentiation-operator 指数运算符

输入

let x = 10 ** 2;

x **= 3;

输出

let x = Math.pow(10, 2);
x = Math.pow(x, 3);

# ES2017

@babel/plugin-transform-async-to-generator 同步函数转换

输入

async function foo() {
  await bar();
}

输出

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }
  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}

function _asyncToGenerator(fn) {
  return function () {
    var self = this,
      args = arguments;
    return new Promise(function (resolve, reject) {
      var gen = fn.apply(self, args);
      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'next', value);
      }
      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
      }
      _next(undefined);
    });
  };
}

function foo() {
  return _foo.apply(this, arguments);
}

function _foo() {
  _foo = _asyncToGenerator(function* () {
    yield bar();
  });
  return _foo.apply(this, arguments);
}

# ES2018

1.@babel/plugin-transform-named-capturing-groups-regex 正则分组

输入

var re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;

console.log(re.exec('1999-02-29').groups.year);

输出

var re = /*#__PURE__*/ _wrapRegExp(/(\d{4})\x2D(\d{2})\x2D(\d{2})/, {
  year: 1,
  month: 2,
  day: 3,
});

console.log(re.exec('1999-02-29').groups.year);

2.@babel/plugin-transform-dotall-regex 多线程正则

输入

/./s;
/./su;

输出

/[\s\S]/;
/[\s\S]/u;

3.@babel/plugin-proposal-unicode-property-regex 正则unicode

输入

var regex = /\p{Script_Extensions=Greek}/u;

输出

var regex =
  /[\u0342\u0345\u0370-\u0373\u0375-\u0377\u037A-\u037D\u037F\u0384\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03E1\u03F0-\u03FF\u1D26-\u1D2A\u1D5D-\u1D61\u1D66-\u1D6A\u1DBF-\u1DC1\u1F00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FC4\u1FC6-\u1FD3\u1FD6-\u1FDB\u1FDD-\u1FEF\u1FF2-\u1FF4\u1FF6-\u1FFE\u2126\uAB65\u{10140}-\u{1018E}\u{101A0}\u{1D200}-\u{1D245}]/u;

4.@babel/plugin-proposal-object-rest-spread 剩余参数

输入

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };

输出

let _x$y$a$b = {
  x: 1,
  y: 2,
  a: 3,
  b: 4
},
    {
  x,
  y
} = _x$y$a$b,
    z = _objectWithoutProperties(_x$y$a$b, ["x", "y"]);

5.@babel/plugin-proposal-async-generator-functions 生成器转换

输入

async function* agf() {
  await 1;
  yield 2;
}

输出

function agf() {
  return _agf.apply(this, arguments);
}

function _agf() {
  _agf = _wrapAsyncGenerator(function* () {
    yield _awaitAsyncGenerator(1);
    yield 2;
  });
  return _agf.apply(this, arguments);
}

# ES2019

@babel/plugin-proposal-optional-catch-binding catch 绑定

输入

try {
  throw 0;
} catch {
  doSomethingWhichDoesNotCareAboutTheValueThrown();
} finally {
  doSomeCleanup();
}

输出

try {
  throw 0;
} catch (_unused) {
  doSomethingWhichDoesNotCareAboutTheValueThrown();
} finally {
  doSomeCleanup();
}

# ES2020

1.@babel/plugin-syntax-bigint 转换bigint

Babel 不支持转换 BigInts。一种建议是使用 JSBI 库,并最终babel-plugin-transform-jsbi-to-bigint在将来运行以将其代码修改为 BigInt。

2.@babel/plugin-syntax-import-meta

3.@babel/plugin-syntax-dynamic-import

4.@babel/plugin-proposal-optional-chaining 可选链

输入

const obj = {
    foo: {
      bar: {
        baz: 42,
      },
    },
  };
  
const baz = obj?.foo?.bar?.baz; // 42

输出

var _obj$foo, _obj$foo$bar;

const obj = {
  foo: {
    bar: {
      baz: 42,
    },
  },
};
const baz =
  obj === null || obj === void 0
    ? void 0
    : (_obj$foo = obj.foo) === null || _obj$foo === void 0
    ? void 0
    : (_obj$foo$bar = _obj$foo.bar) === null || _obj$foo$bar === void 0
    ? void 0
    : _obj$foo$bar.baz; // 42

5.@babel/plugin-proposal-nullish-coalescing-operator 无效合并运算符

输入

var foo = object.foo ?? "default";

输出

var _object$foo;

var foo =
  (_object$foo = object.foo) !== null && _object$foo !== void 0
    ? _object$foo
    : "default";

6.@babel/plugin-proposal-export-namespace-from 命名空间转换

export * as ns from "mod";

# ES2021

1.@babel/plugin-proposal-numeric-separator 数字分割符

输入

let budget = 1_000_000_000_000;

输出

let budget = 1000000000000;

2.@babel/plugin-proposal-logical-assignment-operators 逻辑运算符

输入

a ||= b;
obj.a.b ||= c;

a &&= b;
obj.a.b &&= c;

输出

var _obj$a, _obj$a2;

a || (a = b);
(_obj$a = obj.a).b || (_obj$a.b = c);
a && (a = b);
(_obj$a2 = obj.a).b && (_obj$a2.b = c);

# ES2022

1.@babel/plugin-syntax-top-level-await

Babel 不支持转换顶层 await,但你可以使用 RollupexperimentalTopLevelAwait或 webpack@5 的 experiments.topLevelAwait选项。

2.@babel/plugin-proposal-private-property-in-object 对象中私有属性

输入

class Foo {
  #bar = "bar";

  test(obj) {
    return #bar in obj;
  }
}

输出

var _barBrandCheck = /*#__PURE__*/new WeakSet();

class Foo {
  #bar = (_barBrandCheck.add(this), "bar");

  test(obj) {
    return _barBrandCheck.has(obj);
  }

}

3.@babel/plugin-proposal-class-static-block 类静态代码块

具有静态块的类将被转换为静态私有属性,其初始化程序是包装在 IIAFE(立即调用箭头函数表达式)中的静态块。

输入

class C {
  static #x = 42;
  static y;
  static {
    try {
      this.y = doSomethingWith(this.#x);
    } catch {
      this.y = "unknown";
    }
  }
}

输出

class C {
  static #x = 42;
  static y;
  static #_ = (() => {
    try {
      this.y = doSomethingWith(this.#x);
    } catch {
      this.y = "unknown";
    }
  })();
}

4.@babel/plugin-proposal-class-properties 类属性

输入

class Bork {
  //Property initializer syntax
  instanceProperty = "bork";
  boundFunction = () => {
    return this.instanceProperty;
  };

  //Static class properties
  static staticProperty = "babelIsCool";
  static staticFunction = function () {
    return Bork.staticProperty;
  };
}

let myBork = new Bork();

输出

class Bork {
  constructor() {
    _defineProperty(this, "instanceProperty", "bork");

    _defineProperty(this, "boundFunction", () => {
      return this.instanceProperty;
    });
  }

}

_defineProperty(Bork, "staticProperty", "babelIsCool");

_defineProperty(Bork, "staticFunction", function () {
  return Bork.staticProperty;
});

let myBork = new Bork();