转换类
一、前言
转换前
class Person {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
转换后
-
Babel官方转换
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; }
var Person = /*#__PURE__*/function () {
function Person(name) {
_classCallCheck(this, Person);
this.name = name;
}
_createClass(Person, [{
key: "getName",
value: function getName() {
return this.name;
}
}]);
return Person;
}(); -
ES5 简单转换
function Person(name){
this.name = name;
}
Person.prototype.getName = function(){
return this.name;
}
二、官方实现
const BabelCore = require("@babel/core");
const Types = require("babel-types");
const TransformClasses = require("@babel/plugin-transform-classes");
const sourceCode = `class Person {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
};`;
const targetCode = BabelCore.transform(sourceCode, {
plugins: [TransformClasses],
});
console.log(targetCode.code);
三、模拟实现
3.1 分析语法树结构
ES6类语法树结构如下:
Preview
Preview
ES6类语法树结构如下:
Preview
Preview
3.2 实现类转换插件
const BabelCore = require("@babel/core");
const Types = require("babel-types");
const TransformClasses = require("@babel/plugin-transform-classes");
const sourceCode = `class Person {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
};`;
const TransformClassesSelf = {
visitor: {
ClassDeclaration(nodePath) {
const { node } = nodePath;
const { id } = node;
const { body: classMethods } = node.body;
const nodes = [];
classMethods.forEach((classMethod) => {
if (classMethod.kind === 'constructor') {
const constructor = Types.functionDeclaration(id, classMethod.params, classMethod.body);
nodes.push(constructor);
} else {
const rightExpression = Types.functionExpression(null, classMethod.params, classMethod.body);
const prototypeExpression = Types.memberExpression(id, Types.identifier('prototype'));
const memberExpression = Types.memberExpression(prototypeExpression, classMethod.key);
const assignmentExpression = Types.assignmentExpression('=', memberExpression, rightExpression);
nodes.push(assignmentExpression);
}
});
if (nodes.length === 1) {
nodePath.replaceWith(nodes[0]);
} else {
nodePath.replaceWithMultiple(nodes);
}
},
},
};
const targetCode = BabelCore.transform(sourceCode, {
plugins: [TransformClassesSelf],
});
console.log(targetCode.code);