Статьи

10 языков, которые компилируются в JavaScript

Эта статья содержит список из десяти интересных языков, которые можно скомпилировать в JavaScript для выполнения в браузере или на платформе, такой как Node.js.

Современные приложения имеют различные требования от простых веб-сайтов. Но браузер — это платформа с (в основном) фиксированным набором доступных технологий, и JavaScript остается основным языком для веб-приложений. Любое приложение, которое необходимо запустить в браузере, должно быть реализовано на этом языке.

Мы все знаем, что JavaScript не лучший язык для каждой задачи, и когда речь идет о сложных приложениях, он может не сработать. Чтобы избежать этой проблемы, было создано несколько новых языков и транспортеров существующих, все они производят код, который может работать в браузере без необходимости написания каких-либо строк JavaScript, и вам не нужно думать об ограничениях языка ,

дротик

Dart — это классический объектно-ориентированный язык, в котором все является объектом, а любой объект является экземпляром класса (объекты также могут выполнять функции функций). Он специально создан для создания приложений для браузеров, серверов и мобильных устройств. Он поддерживается Google и является языком, который поддерживает интерфейс следующего поколения AdWords , самый важный продукт Google в плане доходов, что само по себе является доказательством его масштабности.

Язык можно перевести на JavaScript для использования в браузере или напрямую интерпретировать Dart VM, что также позволяет создавать серверные приложения. Мобильные приложения могут быть сделаны с помощью Flutter SDK.

Сложные приложения также требуют зрелого набора библиотек и языковых функций, специально разработанных для этой задачи, и Dart включает все это. Примером популярной библиотеки является AngularDart , версия Angular for Dart.

Это позволяет вам писать типобезопасный код, не будучи слишком навязчивым. Вы можете писать типы, но вы не обязаны это делать, * поскольку они могут быть выведены. Это позволяет быстро создавать прототипы без необходимости продумывать детали, но если у вас есть что-то работающее, вы можете добавить типы, чтобы сделать его более надежным.

Что касается параллельного программирования в ВМ, вместо потоков с разделяемой памятью (Dart является однопоточным), Dart использует то, что они называют Isolates , со своей собственной кучей памяти, где связь достигается с помощью сообщений. В браузере история немного другая: вместо создания новых изолятов вы создаете новых работников .

// 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’s Начать с ресурса Dart .

Машинопись

TypeScript — это расширенный набор JavaScript. Допустимая программа JavaScript также допустима для TypeScript, но с добавленной статической типизацией. Компилятор также может работать как переносчик с ES2015 + на текущие реализации, так что вы всегда получаете самые последние функции.

В отличие от многих других языков, TypeScript сохраняет дух JavaScript без изменений, добавляя только функции, улучшающие правильность кода. Это аннотации типов и другие функциональные возможности, связанные с типами, которые делают написание JavaScript более приятным благодаря включению специализированных инструментов, таких как статические анализаторы, и других инструментов, помогающих в процессе рефакторинга. Кроме того, добавление типов улучшает интерфейсы между различными компонентами ваших приложений.

Поддерживается вывод типов, поэтому вам не нужно писать все типы с самого начала. Вы можете написать быстрые решения, а затем добавить все типы, чтобы быть уверенными в своем коде.

TypeScript также поддерживает расширенные типы, такие как типы пересечений, типы объединений, псевдонимы типов, различимые объединения и средства защиты типов. Вы можете проверить все это на странице Advanced Types на сайте документации TypeScript .

JSX также поддерживается добавлением типов React, если вы используете 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})`;
  }
}

Чтобы узнать больше о typeScript, проверьте, как SitePoint начинает работу со статьей TypeScript .

вяз

Elm — это чисто функциональный язык программирования, который может компилироваться в JavaScript, HTML и CSS. Вы можете создать полноценный сайт, используя только Elm, что делает его отличной альтернативой JavaScript-фреймворкам, таким как React. Приложения, которые вы создаете с его помощью, автоматически используют виртуальную библиотеку DOM, что делает ее очень быстрой. Один большой плюс — это встроенная архитектура, которая позволяет забыть о потоке данных и сосредоточиться на декларации данных и логике.

В Elm все функции чистые, что означает, что они всегда будут возвращать один и тот же вывод для данного ввода. Они не могут делать ничего другого, если вы не укажете это. Например, чтобы получить доступ к удаленному API, вы должны создать командные функции для связи с внешним миром и подписки для прослушивания ответов. Еще один момент для чистоты заключается в том, что значения неизменны: когда вам что-то нужно, вы создаете новые значения, а не модифицируете их.

Принятие Вяза может быть постепенным. Можно общаться с 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

SitePoint имеет удобное начало работы со статьей Elm, если вы хотите узнать больше.

PureScript

PureScript — это чисто функциональный и строго типизированный язык программирования, созданный Филом Фриманом. Он направлен на обеспечение сильной совместимости с доступными библиотеками 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, ознакомьтесь с руководством по началу работы с PureScript на GitHub.

CoffeeScript

CoffeeScript — это язык, целью которого является демонстрация хороших частей JavaScript с более чистым синтаксисом и сохранением семантики. Хотя популярность языка в последние годы снижается, он меняет направление и недавно получил новую основную версию, обеспечивающую поддержку функций ES2015 +.

Код, который вы пишете на CoffeeScript, напрямую переводится в читаемый код JavaScript и поддерживает совместимость с существующими библиотеками. Начиная с версии 2, компилятор создает код, совместимый с последними версиями ECMAScript. Например, каждый раз, когда вы используете classclass Также, если вы используете React, есть хорошие новости: JSX совместим с CoffeeScript.

Отличительной особенностью компилятора является возможность обрабатывать код, написанный в грамотном стиле , где вместо того, чтобы делать акцент в коде и добавлять комментарии в качестве дополнительного, вы пишете комментарии в первую очередь, а код появляется только изредка. Этот стиль программирования был введен Дональдом Кнутом, сделав файл кода очень похожим на техническую статью.

В отличие от других языков, код CoffeeScript можно интерпретировать непосредственно в браузере с помощью библиотеки. Поэтому, если вы хотите создать быстрый тест, вы можете написать свой код в тегах text/coffeescript

 # 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 и, естественно, имеет много общих возможностей. Например, код может быть обработан как данные, и доступна макросистема, что делает возможными методы метапрограммирования. В отличие от других Лиспов, Clojure поддерживает неизменяемые структуры данных, что упрощает управление побочными эффектами.

Синтаксис может показаться пугающим для новичков из-за использования скобок, но у него есть веские причины для этого, и вы наверняка оцените это в долгосрочной перспективе. Этот минимализм в синтаксисе и его возможности синтаксической абстракции делают Lisp мощным инструментом для решения проблем, требующих высокого уровня абстракции.

Хотя Clojure в основном функциональный язык, он не такой чистый, как PureScript или Elm. Побочные эффекты могут все еще случаться, но другие функциональные особенности все еще присутствуют.

ClojureScript использует Google Closure для оптимизации кода, а также имеет совместимость с существующими библиотеками 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 — это язык, созданный и поддерживаемый Facebook, который предлагает новый синтаксис для компилятора OCaml, и код может быть переведен как в JavaScript, так и в собственный код.

Будучи частью семейства ML и самого функционального языка, он, естественно, предлагает мощную, но гибкую систему типов с логическим выводом, алгебраическими типами данных и сопоставлением с образцом. Он также поддерживает неизменяемые типы данных и параметрический полиморфизм (также известный как универсальные в других языках), но, как и в OCaml, также доступна поддержка объектно-ориентированного программирования.

Использование существующих библиотек JavaScript возможно с привязкой по алфавиту . Вы также можете смешивать JavaScript с вашим кодом Reason. Вставленный код 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, чтобы узнать больше.

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 ++.

Сам язык очень мал, но его возможности метапрограммирования делают его привлекательным для реализации функций, которые вы можете найти встроенными в другие языки. Основными блоками для этого являются макросы, шаблоны и обобщения, и с их помощью вы можете реализовывать разные вещи — от простых функций до различных парадигм. Это делает Nim чрезвычайно универсальным языком, который можно адаптировать к вашим потребностям в духе Lisp.

Синтаксическая абстракция 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 не ваш любимый язык, вы все равно можете создавать веб-приложения, не испытывая при этом недостатков технологии. Варианты, доступные для создания этих приложений, могут удовлетворить самые разные вкусы: от чисто функциональных языков, таких как PureScript, до объектно-ориентированных, таких как Dart. И если вам нужно нечто большее, чем перевод на язык «один к одному», у вас есть такие опции, как Elm, которые предоставляют вам инструменты, такие как виртуальный DOM и встроенная архитектура.

Вы пробовали какие-либо языки из этой статьи, или у вас есть один, чтобы рекомендовать? Дайте нам знать об этом в комментариях!