如何將JavaScript轉化成Swift?(二)

LuckyRoc發表於2019-04-03

如何將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......

未完待續。。。

相關文章