zoukankan      html  css  js  c++  java
  • javascript 元编程之-代码修改代码

    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
  • 相关阅读:
    MyEclipse中快速查看错误
    MyEclipse中快速跳转到指定行号位置
    MyEclipse关闭当前正在编辑的页面
    dict、defaultdict 和 OrderedDict 比较
    过滤器的使用
    cookie和session
    session的使用
    Java的常量和变量
    Java面向对象
    Java方法
  • 原文地址:https://www.cnblogs.com/htoooth/p/11370474.html
Copyright © 2011-2022 走看看