JS код сдвиг или преобразователь из JQuery в родной?

Так что, если мне нужно будет изменить код следующим образом:

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

в родной как

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

Я могу сделать что-то вроде ( https://astexplorer.net/)

  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 code shift для таких случаев, как преобразование jQuery в Native, и в конечном итоге просто:

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

1 ответ

Решение

Вы можете использовать jscodeshift для этого. Просто помните об ограничениях:

  • Не каждый идентификатор $ может относиться к JQuery.
  • Там могут быть звонки в JQuery .map функция, которая выглядит как

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

    который вы, вероятно, не сможете поймать.

Тем не менее, это может не быть проблемой в вашей кодовой базе. Написание универсальных кодов трудно (э). Написать тот, который работает для вашей конкретной кодовой базы, проще.

Я бы к следующему:

Найти все CallExpressionчья callee это MemberExpression и это MemberExpression имеет map как его собственность и $(...) как его объект. Вы также можете проверить, что аргумент передан $ является литералом массива. Это снова будет иметь ограничение, которое не будет учитывать 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/

Другие вопросы по тегам