0

我有一个要转换的 codemod

for (var key in foo){}

进入

for (var keys = 0; key < foo; key++){}

我做到了这一点:

return j(file.source)
    .find(j.ForInStatement)
    .replaceWith(p => {

        var prop = p.node.left.declarations[0].id;

        var v = [j.variableDeclarator(prop, null)];
        var varDec = j.variableDeclaration('var', v);
        var binary = j.binaryExpression('<', prop, j.identifier('foo'));
        var uE = j.updateExpression('++', prop, false);
        var block = j.blockStatement([]);

        var forIn = j.forStatement(varDec, binary, uE, block);
        return forIn;
    })
    .toSource();

这让我走到了这一步:

for (var key; key < foo; key++)
  {}

我仍然有点迷失从头开始创建东西......

问题:

  • 我这样做对吗?感觉很冗长,但也许这是要走的路。
  • 如何完成?例如,我失踪了foo.length...

PS: Felix,如果您正在阅读本文,请指出我可以在哪里发送拉取请求以改进文档!在我尝试学习此 API 时,我很乐意提供帮助。哦,还有菲利克斯,你们做的工具真好!

4

1 回答 1

3

直接创建 AST 节点确实很冗长。但是,jscodeshift 导出了一些帮助“方法”,允许您从字符串生成 AST 节点并允许您插入现有的 AST 节点(标记模板 ftw!)。

您上面的示例可以简化为:

  return j(file.source)
    .find(j.ForInStatement)
    .replaceWith(p => {
      var prop = p.node.left.declarations[0].id;
      return statement`for (var ${prop} = 0; ${prop} < foo.length; ${prop}++) ${p.node.body}`;
    })
    .toSource();

演示

请注意,尽管这些模板方法 ( expression, statement, statements) 有其局限性(您只能在可以放置标识符的地方插入 AST 节点)。


如果您想foo.length手动创建,则必须创建一个MemberExpression

在此处输入图像描述

j.memberExpression(
  prop,
  j.identifier('length')
);
于 2016-06-02T16:01:47.733 回答