1

因此,如果我需要像这样更改代码:

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

像原生一样

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 + '!';
});
4

1 回答 1

3

您可以为此绝对使用 jscodeshift。请注意以下限制:

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

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

    您可能无法捕捉到。

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

我会做到以下几点:

找出所有CallExpression的 's,其callee是 aMemberExpression 并且具有作为MemberExpressionmap的属性和$(...)作为它的对象。您还可以验证传递给的参数$是数组文字。那将再次具有它不会考虑的限制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();

https://astexplorer.net/#/kQICtMfd89

于 2016-05-17T00:14:40.793 回答