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();