10 мов програмування, що компілюються в JavaScript

12 хв. читання

Браузер – платформа з фіксованим набором доступних технологій. JavaScript залишається основною мовою програмування для веб – будь-який застосунок, який запускають в браузері має бути написаний цією мовою. В JavaScript є певні обмеження для вирішення завдань. Коли справа доходить до складних програм, можливостей JavaScript може не вистачити. Для вирішення цієї проблеми було створено кілька нових мов програмування та транскомпіляторів, що здатні генерувати код, який може працювати в браузері без написання жодного рядка на JavaScript та не мати обмежень, що накладаються цією мовою. В цій статті ви знайдете перелік із десяти мов програмування, які транскомпілюються в JavaScript для запуску у браузері чи на платформах на кшталт Node.js.

Dart

Dart – класична, об'єктно-орієнтована мова програмування, де все є об'єктом і будь-який об'єкт є класом (об'єкт також може діяти як функція). Мова Dart була спеціально розроблена, щоб створювати застосунки для браузерів, серверів та мобільних пристроїв. Вона підтримується Google та є мовою програмування наступного покоління AdWords UI– найважливішого та найприбутковішого продукту Google, що є доказом її важливості. Мова програмування може «перекладатися» на JavaScript, щоб використовуватись у браузері, чи безпосередньо інтерпретуватися до віртуальної машини Dart VM, завдяки чому можна створювати серверні застосунки. Мобільні програми можна розробляти за допомогою Flutter SDK. Розробка складних застосунків може потребувати повного набору бібліотек та особливостей мов програмування спеціально спроектованих для вирішення подібних завдань. І Dart це все має в собі. Як приклад можна навести бібліотеку AngularDart – версію Angular для Dart. Це дозволяє вам писати безпечний код, який не є інтрузивним. В Dart типи даних можуть бути успадкованими. Також є можливість створювати нові. Завдяки цьому перед розробником відкриваються можливості для швидкого прототипування без нудного та надмірного занурення в деталі. Dart може мати тільки один потік, а можливість конкурентного програмування у віртуальній машині реалізовано у вигляді ізолятів (Isolates), які при цьому мають свій хіп пам'яті. Обмін даними між ізолятами відбувається за участю повідомлень (Messages). В браузері трохи інша історія. Замість створення нових ізолятів, необхідно створювати нові Воркери (Workers).

// Приклад взято з 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');
}
}
/// Генерує потік більш точного оцінювання значення числа π.
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;
// Площа кола A = π⋅r², тому π = A/r².
// Таким чином, коли задаються випадкові точки з x ∈ <0,1>,
// y ∈ <0,1>, співвідношення в одиночному колі
// має бути π / 4. Тому, значення π
// має бути:
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;
}

TypeScript

TypeScript є надбудовою над JavaScript. Програма, що написана на JavaScript також буде працювати і у TypeScript середовищі, але за умови додавання статичної типізації. Компілятор TypeScript може працювати як транскомпілятор для різних версій JavaScript (починаючи з ES2015+ і закінчуючи поточними). Саме тому ви будете мати завжди останні нововведення. На відміну від інших мов програмування, TypeScript зберігає дух JavaScript та має необхідні властивості, що забезпечують більшу надійність коду. Опис типів даних та інша діяльність, що пов'язана з їх визначенням, – все це робить процес написання коду більш приємним, завдяки використанню спеціалізованих засобів (наприклад, статичні аналізатори), які є корисними під час рефакторингу. Крім того, можливість додавання типів може покращити взаємодію між різними компонентами ваших програм. Успадкування типів тут також підтримується, а отже вам не доведеться розробляти всі необхідні типи даних із самого початку. Ви можете нашвидкуруч писати рішення, а вже потім додавати всі необхідні типи для створення надійного коду. TypeScript також підтримує розширені типи даних: типи перетинів, типи об'єднання, типи псевдонімів, дискриміновані об'єднання та guard-типи. Ці типи можна легко знайти на сторінці присвяченій розширеним типам даних, яка знаходиться на сайті документації TypeScript. Крім того, підтримується JSX після додавання типів даних React.

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 повністю функціональна мова програмування, що компілюється до JS, HTML, CSS. Ви можете створити повноцінний сайт, використовуючи лише Elm. І це робить її чудовою альтернативою для JavaScript фреймворків типу React. Програми, які ви будете писати будуть автоматично використовувати віртуальну бібліотеку 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 має свій засіб складання (build tool) проектів написаних на ньому, що має назву 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"
        }
      ]

CoffeeScript

CoffeeScript увібрла у себе все найкраще з JavaScript та забезпечує більш ясний синтаксис та зберігає на місці семантику. Хоча популярність мови програмування поступово зменшувалась протягом останніх років, CoffeeScript змінила напрямок розвитку і тепер отримала велике оновлення і здатна підтримувати ES2015+. Код написаний на CoffeeScript транслюється прямо в JavaScript код, який легко читати, i при цьому зберігається сумісність з бібліотеками. Починаючи з версії 2, компілятор здатний генерувати код сумісний з найновішими версіями ECMAScript. Як приклад можна навести ситуацію коли ви використовуєте class у CoffeeScript, ви також отримаєте class у JavaScript. Також, якщо ви використовуєте React, то для вас є гарна новина: JSX сумісний з CoffeeScript. Особливо вирізняє компілятор здатність обробляти код, написаний в грамотному стилі, для якого характерно писати коментарі в першу чергу, а код з'являється час від часу, замість того, щоб робити акценти на написанні коду, а коментарі використовувати як доповнення. Такий стиль програмування був запроваджений Дональдом Кнутом, що зробило процес написання коду дуже подібним до написання наукової статті. На відміну від інших мов програмування, CoffeeScript може напряму інтерпретуватися браузером за допомогою бібліотеки. Таким чином, якщо ви хочете провести швидкий тест, ви можете написати код в тегах text/coffeescript, і увімкнути компілятор, який на льоту буде транслювати код в JavaScript.

# Призначення змінних:
number   = 42
opposite = true
# Умови:
number = -42 if opposite
# Функції:
square = (x) -> x * x
# Масиви:
list = [1, 2, 3, 4, 5]
# Об'єкти:
math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x
# Повідомлення:
race = (winner, runners...) ->
  print winner, runners
# Перевірка наявності:
alert "I knew it!" if elvis?
# Охоплення масиву:
cubes = (math.cube num for num in list)

ClojureScript

ClojureScript – компілятор, що транслює мову програмування Clojure в JavaScript. Це функціональна мова програмування загального користування з динамічною типізацією та незмінюваними структурами даних. Ця мова тільки одна з усього списку належить до родини Lisp і тому має всі її особливості. Наприклад, код може оброблятися як дані, а доступна макросистема, робить доступними техніки метапрограмування. На відміну від інших Lisp-подібних мов, Clojure підтримує незмінювані структури даних, що робить легшим управління побічними ефектами. Синтаксис може виглядати страхітливим для новачків через спосіб використання дужок, але при тривалому використанні, вам це неодмінно сподобається. Той мінімалізм у синтаксисі разом із синтаксичними абстракціями роблять Lisp потужним засобом для вирішення проблем, де необхідні високі рівні абстракції. Попри те, що Clojure в основному функціональна мова програмування, вона не така чиста як PureScript чи Elm, проте інші особливості, що характерні для функціональних мов програмування все ж таки присутні. ClojureScript використовує Google Closure для оптимізації коду і також має сумісність з JavaScript бібліотеками.

; взято з 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)

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

Reason

Мова програмування Reason створена і підтримується компанією Facebook і пропонує новий синтаксис для компілятора OCaml. Код може транслюватися до JavaScript чи до нативного коду. Оскільки вона є частиною родини ML, а також є функціональною мовою програмування, Reason пропонує потужну і гнучку систему типізації даних з алгебраїчними типами даними та відповідність патернам. Вона також підтримує незмінювані типи даних та параметричний поліморфізм (також відомий як генерик в інших мовах програмування), але, як і в OCaml, є підтримка об'єктно-орієнтованого програмування. Є можливим використання бібліотек JavaScript завдяки bucklescript біндингам. Ви також можете змішувати ваш Reason код з JavaScript. Вставки з JavaScript не будуть суворо перевірятися, але для них будуть працювати швидкі правки чи прототипи. Якщо ви React розробник, також будуть доступні біндинги, крім того є підтримка JSX.

/* Варіант типу, що відповідає шаблону */
let possiblyNullValue1 = None;
let possiblyNullValue2 = Some "Hello@";
switch possiblyNullValue2 {
| None => print_endline "Nothing to see here."
| Some message => print_endline message
};
/* Параметризовані типи */
type universityStudent = {gpa: float};
type response 'studentType = {status: int, student: 'studentType};
let result: response universityStudent = fetchDataFromServer ();
/* Простий типізований об'єкт */
type payload = Js.t {.
  name: string,
  age: int
};
let obj1: payload = {"name": "John", "age": 30};

Haxe

Haxe – мова програмування з багатьма парадигмами; її компілятор може продукувати як бінарники, так і вихідний код на різних мовах. Хоча Haxe забезпечує сувору систему типізації з підтримкою успадкованих типів, вона також може працювати як динамічна мова в тому випадку, якщо кінцева мова підтримує це. Таким самим чином вона забезпечує підтримку різноманітних стилів програмування: об'єктно-орієнтованих, генериків та функціональних. Коли ви пишете Haxe код, ви можете мати декілька кінцевих платформ чи мов програмування для компіляції без необхідності внесення значущих змін. Доступні вставки блоків коду для специфічних мов. Ви можете писати як фронт-енд, так і бек-енд в Haxe і взаємодіяти між ними за допомогою Haxe Remoting для синхронних й асинхронних з'єднань. Код на Haxe буде сумісний з бібліотеками. Haxe також забезпечується гарно розробленою стандартною бібліотекою.

// Приклад взятий з 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);
  }
}

Nim

Nim – статично типізована мова програмування з багатьма парадигмами з мінімалістичним та чутливим до пробілів синтаксисом, яка компілюється до C, C++, JavaScript. Мова сама по собі має дуже малі розміри, але її здатність до метапрограмування робить її привабливою для впровадження різних особливостей та функцій самостійно, вбудовуючи інші мови. Основними блоками для цього слугують макроси, шаблони та генерики – і з ними ви зможете імплементувати від простих особливостей до різноманітних парадигм. Це робить Nim багатогранною мовою програмування, яка може бути адаптована під ваші потреби в традиціях Lisp. Особливості синтаксичної абстракції Nim дозволяє вам адаптувати мову до ваших потреб і це робить можливим DSL. Якщо вам потрібно вирішувати спеціалізовані завдання. Завдяки Nim ви можете досягнути вищого рівня виразності.

# Перевернутий рядок
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)
# Використання шаблонів
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
Помітили помилку? Повідомте автору, для цього достатньо виділити текст з помилкою та натиснути Ctrl+Enter
Codeguida 5.6K
Приєднався: 8 місяців тому
Коментарі (0)

    Ще немає коментарів

Щоб залишити коментар необхідно авторизуватися.

Вхід / Реєстрація