javascript 元编程之-代码修改代码

引言

重构代码是个体力活,特别是在确定重构方案后,剩下就是按方案调整代码,然后进行测试。

如何有好又快的调整到位代码,这是件不容易的事。

简单的代码,可以使用正则表达示进行,如果稍微复杂一点代码,正则表达示就无能为力了。

如我上一篇中讲的修改方法javascript 元编程之 method_missing,我可以在工程中修改一处,如果要修改 50 次接口呢? 我得想想这次重构值不值得了。

还能不能让我随心所欲的写代码了。。。

于是我找到了 jscodeshift,让我能用代码重构我的代码的工具。

jscodeshift 让我有了用代码操作代码的工具。

实现

实例我就使用我上篇文章中的 method_missing 项目,我想把我项目中的接口调用(用url),都调整成 method_missing 调用方式。

如下:


// old
$.ajax('/api/web/project/content/target/mod', {
type: 'post',
dataType: 'json',
data: {
tid: it.targetId,
targetImgId: img.objectId,
pid: pid
}
}).done(function (data, status, jqXhr) {
self.hideLoading();
if (data && data.code === 200 && data.data) {
it.target = data.data
// self.paginationConf.onChange()
}
}).fail(() => { }).always(() => { }) // new
this.$api.update_project_content_target_mod({
tid: it.targetId,
targetImgId: img.objectId,
pid: pid
}).then(function (data, status, jqXhr) {
self.hideLoading();
if (data && data.code === 200 && data.data) {
it.target = data.data
// self.paginationConf.onChange()
}
}).catch(() => { }).finally(() => { })

可以看出新的代码中,把老代码中的 $.ajax 换成了 this.$api,然后用参数生成调用方法名。

最后不仅调整了参数的个数,还调整了参数的值。

想想正则怎么写?

正则应该无能为力。

这时 jscodeshift 就上场了,它能把代码解析成 ast , 然后我们修改 ast,ast 再变成代码。

我的代码如下:


const adapt = require('vue-jscodeshift-adapter'); // 修改 $.ajax
function transform(fileInfo, api) {
const j = api.jscodeshift return j(fileInfo.source)
.find(j.CallExpression, { callee: { object: { name: '$' }, property: { name: 'ajax' } } })
.replaceWith(p => {
const url = p.node.arguments[0]
const setting = p.node.arguments[1]
const urlStr = url.value.replace('/api/web/', '').split('/')
let method = 'get'
let newSetting setting.properties.forEach(i => {
if (i.key.name.toLowerCase() === 'type') {
if (i.value.value.toLowerCase() === 'post') {
method = 'update'
}
} else if (i.key.name.toLowerCase() === 'data') {
newSetting = i.value
}
}); urlStr.unshift(method); return j.callExpression(
j.memberExpression(
j.memberExpression(j.identifier('this'), j.identifier('$api'), false),
j.identifier(urlStr.join('_')), false
), [newSetting])
})
.toSource();
} // 修改 done
function transform1(fileInfo, api) {
const j = api.jscodeshift return j(fileInfo.source)
.find(j.MemberExpression, { property: { name: 'done' } })
.replaceWith(p => {
p.node.property.name = 'then'
return p.node
})
.toSource();
} // 修改 fail
function transform2(fileInfo, api) {
const j = api.jscodeshift return j(fileInfo.source)
.find(j.MemberExpression, { property: { name: 'fail' } })
.replaceWith(p => {
p.node.property.name = 'catch'
return p.node
})
.toSource();
} // 修改 always
function transform3(fileInfo, api) {
const j = api.jscodeshift return j(fileInfo.source)
.find(j.MemberExpression, { property: { name: 'always' } })
.replaceWith(p => {
p.node.property.name = 'finally'
return p.node
})
.toSource();
} module.exports = adapt(transform);
// module.exports = adapt(transform1);
// module.exports = adapt(transform2);
// module.exports = adapt(transform3);

如何使用


# 使用 bash 循环调用
jscodeshift -t src/myTransforms.js filepath

因为我的代码是 vue 的单文件模块,所以我用的了一个第三方插件 vue-jscodeshift-adapter。

总结

jscodeshift 对于大型工程是重构是很有帮助的。可以让你快速改写大量的代码,而且方便测试。

参考链接

  1. vue-jscodeshift-adapter
  2. write-code-to-rewrite-your-code
  3. jscodeshift
  4. astexplorer

javascript 元编程之-代码修改代码的更多相关文章

  1. ES6入门九:Symbol元编程

    JS第七种数据类型:Symbol Symbol的应用场景 11个Symbol静态属性 Symbol元编程 一.JS第七种数据类型:Symbol 在ES6之前的JavaScript的基本数据类型有und ...

  2. 现代c++与模板元编程

    最近在重温<c++程序设计新思维>这本经典著作,感慨颇多.由于成书较早,书中很多元编程的例子使用c++98实现的.而如今c++20即将带着concept,Ranges等新特性一同到来,不得 ...

  3. Spring+SpringMVC+MyBatis整合进阶篇(四)RESTful实战(前端代码修改)

    前言 前文<RESTful API实战笔记(接口设计及Java后端实现)>中介绍了RESTful中后端开发的实现,主要是接口地址修改和返回数据的格式及规范的修改,本文则简单介绍一下,RES ...

  4. 51ak带你看MYSQL5.7源码3:修改代码实现你的第一个Mysql版本

    从事DBA工作多年 MYSQL源码也是头一次接触 尝试记录下自己看MYSQL5.7源码的历程 目录: 51ak带你看MYSQL5.7源码1:main入口函数 51ak带你看MYSQL5.7源码2:编译 ...

  5. u-boot移植(九)---代码修改---NAND

    一.NAND原理 NAND 无地址空间,地址和数据的发送都依赖于LDATA[0:7]这一串数据总线. 不看随机页编程,看到从高位到低位的页,总共分为64个页面,每个页的组成是2K + 64  个byt ...

  6. 不修改代码就能优化ASP.NET网站性能的一些方法 [转]

    不修改代码就能优化ASP.NET网站性能的一些方法 阅读目录 开始 配置OutputCache 启用内容过期 解决资源文件升级问题 启用压缩 删除无用的HttpModule 其它优化选项 本文将介绍一 ...

  7. IDEA 中项目代码修改后不自动生效,需要执行 mvn clean install 才生效

    问题描述 之前项目运行好好的,代码修改完之后会自动编译,编程体验很好. 有一天发现每次修改代码后需要重新使用mvn clean install命令重新编译,异常麻烦. 检查了 IDEA 的配置,已经配 ...

  8. 自修改代码 on the fly 动态编译 即时编译 字节码

    https://zh.wikipedia.org/wiki/自修改代码 自修改代码(Self-modifying code)是指程序在运行期间(Run time)修改自身指令.可能的用途有:病毒利用此 ...

  9. Android之vector代码修改颜色

    前言:google给了很多material design icon,在开发过程中,可以下载下来直接使用,下载地址为https://materialdesignicons.com/ . 1.下载图标,并 ...

随机推荐

  1. 前端构建工具gulp使用 (转)

    http://www.cnblogs.com/starof/p/5194622.html 前端自动化流程工具,用来合并文件,压缩等. Gulp官网 http://gulpjs.com/ Gulp中文网 ...

  2. [windows] install cross-env with cnpm instead of yarn or npm

    环境是 windows下通过vagrant运行虚拟机(ubuntu) Host:windows 10 Guest: ubuntu(vagrant) 根据之前的经验,不要在 Guest环境中执行npm ...

  3. Linux服务器端使用tcpdump抓redis报文

    yum update yum install tcpdump tcpdump host -i ens192 -w /tmp/redis-zsetcapture.cap 其中ens192是网卡名, /t ...

  4. Delphi编写的等长加密与解密

    最近在看一本关于网络游戏服务端开发的书,虽然该书是个空架子,里面没有多少实际的内容(此书评价不好),但其中关于等长加密与解密的代码还是有一定的借鉴作用的.他山之石,可以攻玉.因为书中是C++的代码,所 ...

  5. php获取服务器ip方法

    public static function getServerIp() { if(!empty($_SERVER['SERVER_ADDR'])) { return $_SERVER['SERVER ...

  6. SpringBoot: 6.文件上传(转)

    1.编写页面uploadFile.html <!DOCTYPE html> <html lang="en"> <head> <meta c ...

  7. 线程回调,线程中的队列,事件,greenlet模块,gevent模块,自定义补丁, 单线程实现并发,协程

    1.线程回调 在线程池/进程池每次提交任务,都会返回一个表示任务的对象,Future对象Future对象具备一个绑定方法,add_done_callback 用于指定回调函数 add 意味着可以添加多 ...

  8. C语言递归之二叉树的最大深度

    题目描述 给定一个二叉树,找出其最大深度. 二叉树的深度为根节点到最远叶子节点的最长路径上的节点数. 说明: 叶子节点是指没有子节点的节点. 示例 给定二叉树 [3,9,20,null,null,15 ...

  9. 【DSP开发】串行 RapidIO: 高性能嵌入式互连技术

    串行 RapidIO: 高性能嵌入式互连技术 作者: 德州仪器技术应用工程师 冯华亮/ Brighton Feng/ bf@ti.com 摘要 串行RapidIO针对高性能嵌入式系统芯片间和板间互连而 ...

  10. SQL ------ JDBC 删除指定的某条记录

    package demo; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; ...