js代码转换或从jQuery转换为本机?

时间:2016-05-16 22:43:38

标签: javascript jquery abstract-syntax-tree jscodeshift

所以,如果我需要更改这样的代码:

var amazed = $(['foo', 'bar']).map(function(i, el){
  return this + '!';
});

进入Native就像

var amazed = (['foo', 'bar']).map(function(el, i){
  return el + '!';
});

我可以做(https://astexplorer.net/#/0rIHMowCQf

之类的事情
  return j(file.source)
    .find(j.Identifier).filter(ident => {
    if (ident.node.name == '$') console.log(ident);
    return ident.node.name == '$';
  }).replaceWith('').toSource();

作为第一步,将删除jQuery $符号并留下可以正常工作的(),但感觉我在作弊,因为我只是给CallExpression一个空标识符。我仍然需要发现如何替换参数的顺序。

可以将js代码转换用于此类情况,例如将jQuery转换为Native,最终只是:

var amazed = ['foo', 'bar'].map(function(el, i){
  return el + '!';
});

1 个答案:

答案 0 :(得分:2)

你可以绝对使用jscodeshift。请注意这些限制:

  • 并非每个标识符$都可以引用jQuery。
  • 可能会调用jQuery的.map函数,看起来像

    var foo = $(['foo', 'bar']);
    foo.map(...);
    

    你可能无法捕获。

但是,这些可能不是您的代码库中的问题。编写通用codemod很难(呃)。编写适合您特定代码库的代码更容易。

我想要以下内容:

查找CallExpressioncallee MemberExpression MemberExpression作为其属性map的所有$(...)$ {1}}作为其对象。您还可以验证传递给var foo = []; $(foo);的参数是否为数组文字。这将再次具有不考虑CallExpression的限制。

然后你可以用它的参数替换“内部” return j(file.source) .find(j.CallExpression, { callee: { property: { name: 'map' }, // verify that we call map on $(...) object: { callee: { name: '$', }, // verify that the argument is an array literal arguments: { 0: { type: 'ArrayExpression' } }, } }, }) .forEach(path => { const jQueryArgument = path.node.callee.object.arguments[0]; // replace "inner" CallExpression with argument path.node.callee.object = jQueryArgument; // switch callback arguments var callback = path.node.arguments[0]; callback.params.reverse(); }) .toSource(); 。替换回调的函数参数只是为了。

所有这一切。所有检查都是可选的。测试越不严格,您可以覆盖的用例越多,但获得误报的可能性也会越大。

{{1}}

https://astexplorer.net/#/kQICtMfd89