本文列出了十种有趣的语言,这些语言可以编译为JavaScript,以在浏览器或Node.js之类的平台上执行。
现代应用程序对简单网站的要求不同 。 但是,浏览器是一个平台,具有(大多数)固定技术集,并且JavaScript仍然是Web应用程序的核心语言。 任何需要在浏览器中运行的应用程序都必须使用该语言来实现。
我们都知道JavaScript并不是每项任务的最佳语言,而且对于复杂的应用程序,JavaScript可能不够用。 为了避免这个问题,已经创建了几种新的语言和现有语言的转译器,它们全部产生的代码可以在浏览器中工作,而无需编写任何JavaScript行,也无需考虑该语言的局限性。
镖
Dart是一种古典的,面向对象的语言,其中的所有内容都是一个对象,任何对象都是一个类的实例(对象也可以充当函数)。它是专门为浏览器,服务器和移动设备构建应用程序的。 它由Google维护,是下一代AdWords用户界面的语言,该界面是Google关于收入的最重要产品,它本身就是其强大功能的证明。
该语言可以转换为JavaScript以在浏览器中使用,也可以由Dart VM直接解释,从而也可以构建服务器应用程序。 可以使用Flutter SDK制作移动应用程序。
复杂的应用程序还需要一组专门为此任务设计的成熟的库和语言功能,而Dart包括所有这些功能。 受欢迎的库的一个示例是AngularDart ,它是Angular for Dart的一个版本。
它使您可以编写类型安全的代码,而又不会太麻烦。 您可以编写类型,但是您不必这样做,因为可以推断出它们。 这样就可以快速制作原型,而不必过多考虑细节,但是一旦您有工作可用,就可以添加类型以使其更可靠。
关于VM中的并发编程,Dart而不是共享内存线程(Dart是单线程),而是使用它们所谓的Isolates和自己的内存堆,在内存堆中使用消息进行通信。 在浏览器中,情况有点不同:您无需创建新的隔离,而是创建新的Workers 。
// 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是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})`;
}
}
有关TypeScript的更多信息,请参阅SitePoint的TypeScript入门文章。
榆树
Elm是一种纯函数式编程语言,可以编译为JavaScript,HTML和CSS。 您可以仅使用Elm来构建一个完整的站点,使其成为React等JavaScript框架的绝佳替代品。 与它一起构建的应用程序会自动使用虚拟DOM库,从而使其速度非常快。 一大优点是内置的体系结构,使您无需考虑数据流,而将精力集中在数据声明和逻辑上。
在Elm中,所有函数都是纯函数,这意味着它们将始终为给定输入返回相同的输出。 除非您指定,否则他们将无能为力。 例如,要访问远程API,您将创建命令功能以与外部世界进行通信,并创建订阅以侦听响应。 纯度的另一点是,值是不可变的:当您需要某些东西时,可以创建新值,而不是修改它们。
榆树的采用可以是渐进的。 可以使用ports与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是由Phil Freeman创建的一种纯功能性强类型编程语言。 它的目的是提供与可用的JavaScript库的强兼容性,本质上类似于Haskell,但将JavaScript作为其核心。
PureScript的强项是它的极简主义。 它不包含任何其他语言中必不可少的功能库。 例如,您可以在任务中使用特定的库,而不是在生成器本身中包含生成器和Promise。 您可以为所需的功能选择所需的实现,这可以在使用PureScript时提供高效和个性化的体验,同时使生成的代码尽可能地小。
它的编译器的另一个独特功能是在保持与JavaScript(包括库和工具)的兼容性的同时,编写清晰可读的代码的能力。
与其他语言一样,PureScript有自己的构建工具Pulp ,可以将其与Gulp进行比较,但适用于使用该语言编写的项目。
关于类型系统(与Elm不同,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兼容的代码。 例如,每次使用class
,都会在JavaScript中获得一个class
。 另外,如果您使用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编程语言家族的一个,自然,它具有许多功能。 例如,可以将代码视为数据,并且可以使用宏系统,从而使元编程技术成为可能。 与其他Lisps不同,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()
原因
原因是Facebook创建和维护的一种语言,它为OCaml编译器提供了新的语法,并且该代码可以转换为JavaScript和本机代码。
作为ML系列和一种功能语言本身的一部分,它自然提供了一个功能强大但灵活的类型系统,该系统具有推理,代数数据类型和模式匹配。 它还支持不可变数据类型和参数多态性(在其他语言中也称为泛型 ),但是,如在OCaml中一样,也支持面向对象的编程。
带扣脚本绑定可以使用现有的JavaScript库。 您还可以将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};
有关更多信息,请查看原因网站的“ 原因指南”入门。
哈克斯
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);
}
}
尼姆
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不是您最喜欢的语言,您仍然可以创建Web应用程序而不必忍受该技术的缺点。 从纯函数式语言(如PureScript)到面向对象的语言(如Dart),可用于创建这些应用程序的选项可以满足各种口味。 而且,如果您想要的不仅仅是一对一的语言翻译,还可以使用Elm等选项,这些选项为您提供了诸如虚拟DOM和内置体系结构之类的工具。
您是否尝试过本文中的任何一种语言,或者是否有推荐的语言? 让我们在评论中知道!
From: https://www.sitepoint.com/10-languages-compile-javascript/