十種可編譯成javascript的有趣語言

2020-10-21 21:00:51

本文列出了十種有趣的語言,它們可以編譯成JavaScript,以便在瀏覽器或Node.js之類的平臺上執行。

現代應用程式與簡單的網站有不同的要求。但是瀏覽器是一個擁有(大部分)固定可用技術的平臺,JavaScript仍然是web應用程式的核心語言。任何需要在瀏覽器中執行的應用程式都必須用這種語言實現。

我們都知道JavaScript並不是每個任務的最佳語言,當涉及到複雜的應用程式時,它可能會有不足之處。

為了避免這個問題,已經建立了幾種新語言和現有語言的轉置器,它們都生成了可以在瀏覽器中工作的程式碼,而不需要編寫任何JavaScript行,也不需要考慮該語言的限制。

Dart

DART是一種經典的物件導向語言,其中所有內容都是物件,任何物件都是類的範例(物件也可以充當函數)。它是專門為瀏覽器、伺服器和移動裝置構建應用程式的。

它是由谷歌維護的,是下一代adwords使用者介面的驅動語言,是谷歌最重要的收入產品,這本身就是它在規模上強大的證明。

該語言可以轉換為JavaScript以在瀏覽器中使用,也可以由Dart VM直接解釋,從而也可以構建伺服器應用程式。 可以使用Flutter SDK製作移動應用程式。

複雜的應用程式還需要為該任務專門設計的一組成熟的庫和語言特性,Dart包括所有這些。一個流行庫的例子是AngularDart,它是Dart的Angular版本。

它允許您編寫型別安全的程式碼,而不會太麻煩。您可以編寫型別,但不需要這樣做,*因為可以推斷它們。這允許快速構建原型,而不必過多考慮細節,但是一旦您有了工作,您就可以新增型別,使其更加健壯。

關於VM中的並行程式設計,Dart不是使用共用記憶體執行緒(Dart是單執行緒的),而是使用他們所謂的隔離記憶體堆,在那裡使用訊息來實現通訊。在瀏覽器中,情況有點不同:不是建立新的隔離,而是建立新的worker。

// Example extracted from dartlang.org

import 'dart:async';
import 'dart:math' show Random;

main() async {
  print('Compute π using the Monte Carlo method.');
  await for (var estimate in computePi()) {
    print('π ≅ $estimate');
  }
}

/// Generates a stream of increasingly accurate estimates of π.
Stream<double> computePi({int batch: 1000000}) async* {
  var total = 0;
  var count = 0;
  while (true) {
    var points = generateRandom().take(batch);
    var inside = points.where((p) => p.isInsideUnitCircle);
    total += batch;
    count += inside.length;
    var ratio = count / total;
    // Area of a circle is A = π⋅r², therefore π = A/r².
    // So, when given random points with x ∈ <0,1>,
    // y ∈ <0,1>, the ratio of those inside a unit circle
    // should approach π / 4. Therefore, the value of π
    // should be:
    yield ratio * 4;
  }
}

Iterable<Point> generateRandom([int seed]) sync* {
  final random = new Random(seed);
  while (true) {
    yield new Point(random.nextDouble(), random.nextDouble());
  }
}

class Point {
  final double x, y;
  const Point(this.x, this.y);
  bool get isInsideUnitCircle => x * x + y * y <= 1;
}

有關更多閱讀,推薦Dart的Dart入門資源。

TypeScript

TypeScript是JavaScript的超集。一個有效的JavaScript程式也是有效的TypeScript,但是新增了靜態型別。編譯器還可以作為從ES2015+到當前實現的轉換程式,因此您總是可以獲得最新的特性。

與許多其他語言不同,TypeScript保留了JavaScript的精神,只是新增了一些特性來提高程式碼的健壯性。這些是型別註釋和其他與型別相關的功能,它們使編寫JavaScript更加令人愉快,這要感謝支援靜態分析程式等專門工具和其他工具來幫助重構過程。

此外,新增型別還可以改進應用程式不同元件之間的介面。

支援型別推斷,因此不必從頭編寫所有型別。您可以編寫快速的解決方案,然後新增所有型別,以便對您的程式碼有信心。

TypeScript還支援高階型別,比如交集型別、聯合型別、型別別名、區分的聯合和型別保護。您可以在TypeScript檔案站點的高階型別頁面中檢視所有這些。

如果使用react,還可以通過新增react型別來支援jsx:

class Person {
  private name: string;
  private age: number;
  private salary: number;

  constructor(name: string, age: number, salary: number) {
    this.name = name;
    this.age = age;
    this.salary = salary;
  }

  toString(): string {
    return `${this.name} (${this.age}) (${this.salary})`;
  }
}

Elm

Elm是一種純函數語言程式設計語言,可以編譯為JavaScript、HTML和CSS。您可以使用Elm構建一個完整的站點,使其成為React等JavaScript框架的一個很好的替代品。

使用它構建的應用程式自動使用一個虛擬DOM庫,使其執行非常快。一個很大的優點是內建的體系結構,它使您忘記了資料流,轉而專注於資料宣告和邏輯。

在Elm中,所有函數都是純函數,這意味著對於給定的輸入,它們總是返回相同的輸出。他們不能做任何事情,除非你指定它。例如,要存取遠端API,您需要建立命令函數來與外部世界通訊,並建立訂閱來偵聽響應。

純度的另一點是,值是不可變的:當您需要某些東西時,您建立新的值,而不是修改它們。

Elm的採用可以是漸進的。可以使用埠與JavaScript和其他庫通訊。雖然Elm還沒有達到版本1,但是它已經被用於複雜和大型應用程式,這使得它成為複雜應用程式的可行解決方案。

Elm最吸引人的特性之一是初學者友好的編譯器,它不是生成難以閱讀的訊息,而是生成幫助您修復程式碼的程式碼。如果你正在學習這門語言,編譯器本身會有很大的幫助。

module Main exposing (..)

import Html exposing (..)


-- MAIN


main : Program Never Model Msg
main =
    Html.program
        { init = init
        , update = update
        , view = view
        , subscriptions = subscriptions
        }



-- INIT


type alias Model = String


init : ( Model, Cmd Msg )
init = ( "Hello World!", Cmd.none )


-- UPDATE


type Msg
    = DoNothing


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        DoNothing ->
            ( model, Cmd.none )


-- VIEW


view : Model -> Html Msg
view model =
    div [] [text model]


-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.none

PureScript

purescript是一種純功能的強型別程式語言,由phil freeman建立。它的目標是提供與可用javascript庫的強相容性,在精神上類似於haskell,但保持javascript的核心。

PureScript的一個優點是它的極簡主義。它不包含任何在其他語言中被認為是必不可少的功能庫。例如,您可以為任務使用特定的庫,而不是在編譯器本身中包含生成器和承諾。

您可以為您需要的特性選擇您想要的實現,這允許在使用PureScript時獲得高效和個性化的體驗,同時使生成的程式碼儘可能小。

它的編譯器的另一個獨特的特性是,在保持與JavaScript相容的同時,能夠生成乾淨且可讀的程式碼,包括庫和工具。

與其他語言一樣,PureScript也有自己的構建工具Pulp,它可以與Gulp進行比較,但是對於用這種語言編寫的專案來說。

關於型別系統——不像Elm,它是另一種類似於ml的語言——PureScript支援高階型別特性,比如高階型別和型別類,它們來自Haskell,允許建立複雜的抽象:

module Main where

import Prelude
import Data.Foldable (fold)
import TryPureScript

main =
    render $ fold
      [ h1 (text "Try PureScript!")
      , p (text "Try out the examples below, or create your own!")
      , h2 (text "Examples")
      , list (map fromExample examples)
      ]
  where
    fromExample { title, gist } =
      link ("?gist=" <> gist) (text title)

    examples =
      [ { title: "Algebraic Data Types"
        , gist: "37c3c97f47a43f20c548"
        }
      , { title: "Loops"
        , gist: "cfdabdcd085d4ac3dc46"
        }
      , { title: "Operators"
        , gist: "3044550f29a7c5d3d0d0"
        }
      ]

要使用purescript執行下一步,請檢視github上的purescript入門指南。

CoffeeScript

CoffeeScript是一種語言,旨在公開JavaScript的優秀部分,同時提供更乾淨的語法和保持語意。儘管近年來該語言的受歡迎程度有所下降,但它正在改變方向,最近又獲得了一個新的主要版本,支援ES2015+特性。

您在CoffeeScript中編寫的程式碼將直接轉換為可讀的JavaScript程式碼,並保持與現有庫的相容性。 從版本2開始,編譯器將生成與最新版本的ECMAScript相容的程式碼。

例如,每次使用類時,您都會在JavaScript中獲得一個類。 另外,如果您使用React,則有個好訊息:JSX與CoffeeScript相容。

編譯器的一個非常獨特的功能是能夠處理以素養風格編寫的程式碼,您無需在程式碼中強調重點和新增註釋,而是首先編寫註釋,並且程式碼僅偶爾出現。 Donald Knuth引入了這種程式設計風格,使程式碼檔案與技術文章非常相似。

與其他語言不同,CoffeeScript程式碼可以在瀏覽器中使用庫直接解釋。因此,如果你想建立一個快速測試,你可以用text/coffeescript指令碼標籤編寫程式碼,幷包含編譯器,編譯器會實時將程式碼翻譯成JavaScript:

# Assignment:
number   = 42
opposite = true

# Conditions:
number = -42 if opposite

# Functions:
square = (x) -> x * x

# Arrays:
list = [1, 2, 3, 4, 5]

# Objects:
math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

# Splats:
race = (winner, runners...) ->
  print winner, runners

# Existence:
alert "I knew it!" if elvis?

# Array comprehensions:
cubes = (math.cube num for num in list)

coffeescript站點有一個方便的coffeescript 2資源入門

ClojureScript

ClojureScript是一個編譯器,它將Clojure程式語言翻譯成JavaScript。它是一種通用的函數式語言,具有動態型別和對不可變資料結構的支援。

它是這個列表中唯一屬於Lisp程式語言家族的,並且自然地,它共用了許多特性。例如,可以將程式碼視為資料,並且可以使用宏系統,從而使超程式設計技術成為可能。與其他lisp不同,Clojure支援不可變的資料結構,這使得副作用的管理更加容易。

由於使用了括號,語法對新手來說可能有些嚇人,但這樣做有其深刻的原因,從長遠來看,您肯定會喜歡它。語法中的這種極簡主義及其語法抽象功能使Lisp成為解決需要高抽象級別的問題的強大工具。

雖然Clojure主要是一種函數式語言,但它不像PureScript或Elm那樣純粹。副作用仍然可能發生,但是其他功能特性仍然存在。

ClojureScript使用谷歌閉包進行程式碼優化,並且與現有的JavaScript庫相容:

; Extracted from https://github.com/clojure/clojurescript/blob/master/samples/dom/src/dom/test.cljs

(ns dom.test
  (:require [clojure.browser.event :as event]
            [clojure.browser.dom   :as dom]))

(defn log [& args]
  (.log js/console (apply pr-str args)))

(defn log-obj [obj]
  (.log js/console obj))

(defn log-listener-count []
  (log "listener count: " (event/total-listener-count)))

(def source      (dom/get-element "source"))
(def destination (dom/get-element "destination"))

(dom/append source
            (dom/element "Testing me ")
            (dom/element "out!"))

(def success-count (atom 0))

(log-listener-count)

(event/listen source
              :click
              (fn [e]
                (let [i (swap! success-count inc)
                      e (dom/element :li
                                     {:id "testing"
                                      :class "test me out please"}
                                     "It worked!")]
                  (log-obj e)
                  (log i)
                  (dom/append destination
                              e))))

(log-obj (dom/element "Text node"))
(log-obj (dom/element :li))
(log-obj (dom/element :li {:class "foo"}))
(log-obj (dom/element :li {:class "bar"} "text node"))
(log-obj (dom/element [:ul [:li :li :li]]))
(log-obj (dom/element :ul [:li :li :li]))
(log-obj (dom/element :li {} [:ul {} [:li :li :li]]))
(log-obj (dom/element [:li {:class "baz"} [:li {:class "quux"}]]))

(log-obj source)
(log-listener-count)

要了解更多,請存取ClojureScript站點的ClojureScript資源入門

Scala.js

Scala.js是將Scala程式語言轉換為JavaScript的編譯器。 Scala是一種語言,旨在將來自物件導向和函數語言程式設計的思想融合為一種語言,以建立功能強大且易於採用的工具。

作為一種強型別語言,您可以從具有部分型別推斷的靈活型別系統中獲益。大多數值都可以推斷,但是函數引數仍然需要顯式的型別註釋。

雖然支援許多常見的物件導向模式(例如,每個值都是一個物件,操作是方法呼叫),但是也可以獲得一些函數特性,比如支援一流函數和不可變資料結構。

Scala.js的一個特殊優勢是,您可以從熟悉的物件導向的方法開始,然後根據需要以自己的速度遷移到功能更強的方法,而不需要做很多工作。另外,現有的JavaScript程式碼和庫與Scala程式碼相容。

初學Scala的開發人員會發現這種語言與JavaScript並沒有太大的不同。比較以下等價程式碼:

// JavaScript
var xhr = new XMLHttpRequest();

xhr.open("GET",
  "https://api.twitter.com/1.1/search/" +
  "tweets.json?q=%23scalajs"
);
xhr.onload = (e) => {
  if (xhr.status === 200) {
    var r = JSON.parse(xhr.responseText);
    $("#tweets").html(parseTweets(r));
  }
};
xhr.send();
// Scala.js
val xhr = new XMLHttpRequest()

xhr.open("GET",
  "https://api.twitter.com/1.1/search/" +
  "tweets.json?q=%23scalajs"
)
xhr.onload = { (e: Event) =>
  if (xhr.status == 200) {
    val r = JSON.parse(xhr.responseText)
    $("#tweets").html(parseTweets(r))
  }
}
xhr.send()

檢視scala.js「scala.js入門」檔案瞭解更多資訊。

Reason

Reason是Facebook建立和維護的一種語言,它為OCaml編譯器提供了一種新的語法,程式碼可以翻譯成JavaScript和原生程式碼。

作為ml家族和函數語言本身的一部分,它自然提供了一個強大而靈活的型別系統,包括推理、代數資料型別和模式匹配。它還支援不可變的資料型別和引數多型性(在其他語言中也稱為泛型),但與ocaml一樣,也支援物件導向程式設計。

使用現有的JavaScript庫可以使用bucklescript繫結。您還可以在理性程式碼中混合使用JavaScript。插入的JavaScript程式碼不會被嚴格檢查,但是對於快速修復或原型來說,它工作得很好。

如果您是react開發人員,則可以使用繫結,並且該語言還支援jsx:

/* A type variant being pattern matched */

let possiblyNullValue1 = None;
let possiblyNullValue2 = Some "Hello@";

switch possiblyNullValue2 {
| None => print_endline "Nothing to see here."
| Some message => print_endline message
};

/* Parametrized types */

type universityStudent = {gpa: float};
type response 'studentType = {status: int, student: 'studentType};
let result: response universityStudent = fetchDataFromServer ();

/* A simple typed object */

type payload = Js.t {.
  name: string,
  age: int
};
let obj1: payload = {"name": "John", "age": 30};

檢視Reason站點的《Reason Guide入門》瞭解更多資訊。

Haxe

Haxe是一種多正規化程式語言,它的編譯器可以用其他語言生成二進位制檔案和原始碼。

雖然Haxe提供了一個支援型別推斷的嚴格型別系統,但是如果目標語言支援它,它也可以作為動態語言工作。同樣,它還支援各種程式設計風格,如物件導向、泛型和函數式。

當您編寫Haxe程式碼時,您可以針對幾個平臺和語言進行編譯,而不需要進行大量更改。還可以使用特定於目標的程式碼塊。

您可以使用相同的程式碼在haxe中編寫後端和前端,並使用haxe remoting實現同步和非同步連線的通訊。

正如所料,Haxe程式碼相容現有庫,但它也提供了一個成熟的標準庫:

// Example extracted from http://code.haxe.org

extern class Database {
  function new();
  function getProperty<T>(property:Property<T>):T;
  function setProperty<T>(property:Property<T>, value:T):Void;
}

abstract Property<T>(String) {
  public inline function new(name) {
    this = name;
  }
}

class Main {
  static inline var PLAYER_NAME = new Property<String>("playerName");
  static inline var PLAYER_LEVEL = new Property<Int>("playerLevel");

  static function main() {
    var db = new Database();

    var playerName = db.getProperty(PLAYER_NAME);
    trace(playerName.toUpperCase());

    db.setProperty(PLAYER_LEVEL, 1);
  }
}

檢視haxe站點的haxe頁面入門瞭解更多資訊。

Nim

Nim是一種靜態型別的多正規化程式語言,具有極簡主義和對空格敏感的語法,可以編譯成JavaScript以及C、c++。

該語言本身非常小,但是它的超程式設計功能使得您可以自己實現其他語言內建的特性。它的構建塊是宏、模板和泛型,使用它們可以實現從簡單功能到不同範例的各種功能。本著Lisp的精神,這使得Nim成為一種非常通用的語言,可以根據您的需要進行調整。

Nim的語法抽象特性允許您根據問題調整語言,從而使真正的dsl成為可能。如果你有特殊的任務要解決,你可以得到更高的表達能力:

# Reverse a string
proc reverse(s: string): string =
  result = ""
  for i in countdown(high(s), 0):
    result.add s[i]

var str1 = "Reverse This!"
echo "Reversed: ", reverse(str1)

# Using templates
template genType(name, fieldname: expr, fieldtype: typedesc) =
  type
    name = object
      fieldname: fieldtype

genType(Test, foo, int)

var x = Test(foo: 4566)
echo(x.foo) # 4566

nim站點有一些有用的入門檔案,以獲取更多資訊。

結論

如果JavaScript不是您最喜歡的語言,您仍然可以建立web應用程式,而不必忍受該技術的缺點。用於建立這些應用程式的選項可以滿足各種各樣的需求,從純函數語言(如PureScript)到物件導向語言(如Dart)。

如果您想要比一對一語言翻譯更多的東西,您可以選擇Elm,它為您提供了虛擬DOM和內建體系結構等工具。

相關免費學習推薦:

以上就是十種可編譯成javascript的有趣語言的詳細內容,更多請關注TW511.COM其它相關文章!