Skip to content

Commit

Permalink
feat: 实现class转es5
Browse files Browse the repository at this point in the history
  • Loading branch information
okbug committed Nov 19, 2021
1 parent 500bafd commit a03ffe0
Show file tree
Hide file tree
Showing 5 changed files with 227 additions and 3 deletions.
8 changes: 5 additions & 3 deletions learnWebpack/ast-demo/2.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const core = require('@babel/core');
const types = require('babel-types');
const plugin = require('babel-plugin-transform-es2015-arrow-functions');
const plugin1 = require('babel-plugin-transform-es2015-arrow-functions');
const plugin2 = require('@babel/plugin-transform-classes');

const code = `
const sum = (a, b) => a + b;
`
// babel/core 本身只有 生成、遍历、生成 代码的功能,和上面的三个工具一样
// 它本身不会在代码遍历的时候做一个处理,除了用插件等方法
let target = core.transform(code, {
plugins: [plugin]
plugins: [plugin1]
})
// console.log(target.code);

Expand Down Expand Up @@ -40,4 +41,5 @@ let target2 = core.transform(code, {
plugins: [myPlugin]
})

console.log(target2.code)
// console.log(target2.code)

50 changes: 50 additions & 0 deletions learnWebpack/ast-demo/3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
const core = require('@babel/core');
const types = require('babel-types');
const plugin2 = require('@babel/plugin-transform-classes');


let code2 = `
class A {
constructor(name) {
this.name = name
}
getName() {
return this.name
}
}
`


let res2 = core.transform(code2, {
plugins: [plugin2]
})
const myClassTransformPlugin = {
visitor: {
ClassDeclaration(nodePath) {
// console.log(nodePath)
let {node} = nodePath;
let {id} = node;
let body = []
let classMethods = node.body.body; // 方法: constructor, getName
classMethods.forEach(method => {
if (method.kind === 'construcotr') { // 构造函数的话,就创建一个函数
let ctorFunc = types.functionDeclaration(id, method.params, method.body, method.generator, method.async);
body.push(ctorFunc);
} else { // 类上的方法
let left = types.memberExpression(types.memberExpression(id, types.identifier('prototype')), method.key)
let right = types.functionExpression(method.key /* 函数的名字 这里传null就是匿名函数 */, method.params, method.body, method.generator, method.async);

let func = types.assignmentExpression('=', left, right)
body.push(func)
}
});
nodePath.replaceWithMultiple(body)
}
}
}

let res3 = core.transform(code2, {
plugins: [myClassTransformPlugin]
})
console.log(res3.code)
98 changes: 98 additions & 0 deletions learnWebpack/ast-demo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,4 +133,102 @@ const sum = function (a, b) {

```js

```


## 使用babel转换ES6的class

安装插件
`npm install @babel/plugin-transform-classes -D`


注意事项:
编写插件,要去看下转前和转后的AST结构
找出各自的区别,并且根据AST结构转换
能复用就复用

代码

```js
const core = require('@babel/core');
const types = require('babel-types');
const plugin2 = require('@babel/plugin-transform-classes');


let code2 = `
class A {
constructor(name) {
this.name = name
}
getName() {
return this.name
}
}
`


let res2 = core.transform(code2, {
plugins: [plugin2]
})

console.log(res2.code)
```

结果:

```js
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); return Constructor; }

let A = /*#__PURE__*/function () {
function A(name) {
// 这个是检查类有没有被直接调用的,暂时先注释掉
// _classCallCheck(this, A);

this.name = name;
}

// 给A的prototype加上getName方法
_createClass(A, [{
key: "getName",
value: function getName() {
return this.name;
}
}]);

return A;
}();
```


实现:
```js
const myClassTransformPlugin = {
visitor: {
ClassDeclaration(nodePath) {
// console.log(nodePath)
let {node} = nodePath;
let {id} = node;
let body = []
let classMethods = node.body.body; // 方法: constructor, getName
classMethods.forEach(method => {
if (method.kind === 'construcotr') { // 构造函数的话,就创建一个函数
let ctorFunc = types.functionDeclaration(id, method.params, method.body, method.generator, method.async);
body.push(ctorFunc);
} else { // 类上的方法
let left = types.memberExpression(types.memberExpression(id, types.identifier('prototype')), method.key)
let right = types.functionExpression(method.key /* 函数的名字 这里传null就是匿名函数 */, method.params, method.body, method.generator, method.async);

let func = types.assignmentExpression('=', left, right)
body.push(func)
}
});
nodePath.replaceWithMultiple(body)
}
}
}
```
73 changes: 73 additions & 0 deletions learnWebpack/ast-demo/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions learnWebpack/ast-demo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@babel/plugin-transform-classes": "^7.16.0",
"babel-plugin-transform-es2015-arrow-functions": "^6.22.0",
"babel-types": "^6.26.0"
}
Expand Down

0 comments on commit a03ffe0

Please sign in to comment.