如何将JavaScript转化成Swift?(二)

2,261 阅读3分钟

如何将JavaScript转化成Swift?(一)

如何将JavaScript转化成Swift?(二)

目前已经实现的效果

昨天让同事随意写了一段JavaSCript代码:

function showdata() {
  var array = [0, 1, 2, 3, 4];
  var result = true;

  if (result) {
    for (let index = 0; index < array.length; index++) {
      console.log(array[index]);
    }
  } else {
    console.log("noooooo!")
  }
  var obj = {
    name: 'wuli',
    sex: 0,
    age: 21
  };
  var string = "woxinshensihai";
  if (result) {
    console.log(string)
  }
  console.log(obj);
}

然后用翻译程序进行翻译,结果如下:

func showdata() {
    var array = [
        0,
        1,
        2,
        3,
        4,
    ]
    var result: Bool = true
    if result {
        for (index, item) in array.enumerated() {
            print(array[index])
        }
    } else {
        print("noooooo!")
    }
    var obj = NamesexageModel(name: "wuli", sex: 0, age: 21)
    var string: String = "woxinshensihai"
    if result {
        print(string)
    }
    print(obj)
}

生成的Model文件:

class NamesexageModel: NSObject { 
  var name: String
  var sex: Int
  var age: Int
}

从效果来看感觉还可以。。。

For 循环翻译

上篇文章中没有涉及 for 循环的翻译,这里补充一下:

JavaScriptFor写法和Swift中的差异比较大,主要是因为Javascript 中的 Array 并不像大部分其他语言的数组。首先, Javascript 中的 Array 在内存上并不连续,其次, Array 的索引并不是指偏移量。实际上,Array 的索引也不是 Number 类型,而是 String 类型的。我们可以正确使用如 array[0] 的写法的原因是语言可以自动将 Number 类型的0转换成 String 类型的 “0”

C 风格的 for 循环

这种写法应该是JavaScript中用的最多的

for (let index = 0; index < array.length; index++) {
    console.log(array[index]);
}

但是Swift自从Swift3.0开始不再支持C-Type的写法,这就有点蛋疼了

Swift中的for循环写法

for (index, item) in array.enumerated() {
    print(array[index])
}

对比两种语言for循环的实现,for循环方法体内部差不多,但是for循环的写法相差很多,所以我们主要修改 let index = 0; index < array.length; index++ 这一段代码

先看一下for循环的AST:

"body": [
    {
      "type": "ForStatement",
      "init": {
        "type": "VariableDeclaration",
        "declarations": [
          {
            "type": "VariableDeclarator",
            "id": {
              "type": "Identifier",
              "name": "index"
            },
            "init": {
              "type": "Literal",
              "value": 0,
              "raw": "0"
            }
          }
        ],
        "kind": "let"
      },
      "test": {
        "type": "BinaryExpression",
        "left": {
          "type": "Identifier",
          "name": "index"
        },
        "operator": "<",
        "right": {
          "type": "MemberExpression",
          "object": {
            "type": "Identifier",
            "name": "array"
          },
          "property": {
            "type": "Identifier",
            "name": "length"
          },
          "computed": false
        }
      },
      "update": {
        "type": "UpdateExpression",
        "operator": "++",
        "prefix": false,
        "argument": {
          "type": "Identifier",
          "name": "index"
        }
      }
      ...
      ...

body 下面的节点是 ForStatement 说明执行的是 escodegen.js 中的 ForStatement 方法,想要从 for (let index = 0; index < array.length; index++) { 转换成 for (index, item) in array.enumerated() { 我们只需要获取到 index关键字、array关键字即可

if (stmt.test) {
  // 获取 index 关键字
  result.push(stmt.test.left.name)
  result.push(', item) in ')
  // 获取 array 关键字
  result.push(stmt.test.right.object.name)
  result.push('.enumerated()')
} 

这样就可以生成 for (index, item) in array.enumerated()

这一段代码用来生成 index ++)只需要将它注释掉或者删除即可

if (stmt.update) {
    result.push(space);
    result.push(that.generateExpression(stmt.update, Precedence.Sequence, E_TTT));
    result.push(')');
} else {
    result.push(')');
}

ForIn for 循环

for (index in array) {
 console.log(array[index]);
}

ForOf for 循环

for (let item of array) {
  console.log(item);
}

Swift中对应的写法:

for item in array {
    print(item)
}

这里翻译比较简单 只需要将 of 改成 in 即可

代码格式化

翻译程序生成的代码在格式方面不是很美观,这里借助 swiftformat 来对代码进行格式化,swiftformat 的安装很简单,只需要:

> brew update
> brew install swiftformat

通过 JavaScript 执行 swiftformat fileName.swift --swiftversion 4.2

const { exec } = require('child_process');
exec('swiftformat ./Swift_Code/' + fileName + '.swift --swiftversion 4.2 ', (err, stdout, stderr) => {
    if(err) {
        return;
    }
})

关于如何翻译 JavaScript 的网络请求,由于 JavaScriptSwift 都有各自的网络请求库,这里需要统一方法名、参数,每个语言也需要封装各自的网络请求库;其次,SwiftJSON解析需要一个ClassModel,这里需要将 JSON 转 Swift Model Class......

未完待续。。。