Alternative zu JavaScript

Ich bin nicht wirklich glücklich mit JavaScript.

Hier etwas Weinendes:

  • keine Mengenoperationen
  • Vererbung nicht so einfach wie in Python
  • Verschachtelte Funktionsdefinitionen, Callbacks, sind schwer zu debuggen

Erforderliche Funktionen:

  • Open Source
  • muss im Browser ohne zusätzliches Plugin ausgeführt werden
Ich bezweifle, dass noch etwas anderes existiert, zumindest mit der Unterstützung, die JS hat. Grundsätzlich haben Browser JavaScript längst zum De-facto-Standard „erklärt“. Aktuelle Browser interpretieren keine andere Sprache. Die einzige "Alternative", die mir einfällt, ist VBScript, das unter Internet Explorer ausgeführt wird, das es sonst nirgendwo gibt.
@Alejandro AFAIK Es gibt Sprachen, die zu JS "kompilieren". Aber ich habe keine Ahnung vom Stand der Technik.

Antworten (5)

Die einzige Sprache, die das aktuelle Ziel von JavaScript in Browsern portabel füllen kann, ist JavaScript. Stellen Sie sicher, dass Sie den neuesten ECMAScript-Standard (ES2016/2017) verwenden, und verwenden Sie bei Bedarf einen Transpiler wie BabelJS, um JS nach einem früheren Standard auszugeben.

Wenn Ihnen das nicht ausreicht, können andere Sprachen zu JavaScript herunterkompilieren.

TypeScript ist eine Obermenge von JavaScript (das bedeutet, dass alle gültigen JS gültige TS sind). Es führt jedoch Elemente der statischen Typisierung und andere typ- und vererbungsbezogene Abstraktionen über „Standard-JS“ ein (gemäß der ES2016-Syntax, sofern vorhanden), was eine umfassendere Debug-Erfahrung ermöglicht und auf gängiges JS heruntertranspiliert, das jeder Browser unterstützt. Es ist kostenlos und Open Source, unterstützt von Microsoft und ein Favorit von Angular. Die meisten populären IDEs haben (ein) Plugin(s) zur Verfügung, um die TypeScript-Entwicklung so einfach wie möglich zu machen.

Kotlin ist eine JVM-Sprache, die ursprünglich als besseres Java entwickelt und kürzlich von Android als native Sprache übernommen wurde. Es hat auch erstklassige Unterstützung für ein JS-Target (ab 1.1). Wenn Sie wirklich echtes OOP machen wollen, dann ist dies wahrscheinlich eine der besseren Optionen, da Kotlin zuerst ein Java-Derivat war und Java (fast) reines OOP ist. Natürlich unterstützt Kotlin auch Code im funktionaleren Stil, der in den meisten Fällen als idiomatischer gilt und in der gesamten JS-Welt immer beliebter wird. Kotlin ist Open Source und wurde von JetBrains, den Entwicklern von IntelliJ IDEA, entwickelt. Offizielle Plugins für die Entwicklung sind für IDEA und Eclipse verfügbar, mit Community-gesteuerten Plugins für die meisten anderen IDEs.

Es gibt andere Sprachen, die in JavaScript transpilieren. Wenn WebAssembly weithin unterstützt wird, werden hoffentlich die meisten Sprachen in der Lage sein, das Web als Kompilierungsziel zu unterstützen.


Seit Dezember 2017 unterstützen alle gängigen Browser WebAssembly. C, C++ und Rust haben alle vorhandene Ziele für WebAssembly mit LLVM und/oder EmScripten. WebAssembly ist noch jung und es gibt noch Wachstumsschmerzen, aber es ist brauchbar. Siehe Welche Sprachen können für Webassembly (oder wasm) kompiliert werden? und Mawgs Antwort auf diese Frage für weitere Informationen.

Außerdem habe ich JS mehr verwendet, seit ich diese Antwort ursprünglich geschrieben habe. Solange Sie modernes JS mit moderner Syntax schreiben, ist es ziemlich gut. Mit async/await ist asynchroner Code viel einfacher zu handhaben, und das Verteilen/Destrukturieren erleichtert auch bestimmte Dinge. JavaScript wird wirklich pythonisch.


Es ist Januar 2017 und die WebAssembly-Magie, die ich vorhergesagt habe, kommt. Sie können immer noch nicht nahtlos auf Web-APIs zugreifen, aber mit dem Parcel Zero-Configuration Web Application Bundler können Sie einfach (einfaches) Rust fn in JS importieren !

[Aktualisierung der akzeptierten Antwort zum Nutzen zukünftiger Leser]:

Wie von @CAD97 prophezeit, wird WebAssembly jetzt von allen gängigen Browsern unterstützt.

Wenn Sie die Menge an JS reduzieren möchten, die Sie codieren (Sie können es nicht vollständig eliminieren), dann Google für WebAssembly, wenn Sie in C, C++ oder Rust codieren können.

Hier ist ein sehr einfaches Beispiel aus diesem Tutorial :

Nehmen Sie den C-Code:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <emscripten/emscripten.h>

int main(int argc, char ** argv) {
    printf("WebAssembly module loaded\n");
}

int EMSCRIPTEN_KEEPALIVE roll_dice() {
    srand ( time(NULL) );
    return rand() % 6 + 1;
}

kompilieren Sie es mit dem Befehl zu WebAssemblyemcc dice-roll.c -s WASM=1 -O3 -o index.js

und rufen Sie die WebAssembly Ihres C-Codes in Ihrem HTML auf:

<!DOCTYPE html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>WebAssembly Example</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
  </head>
  <body>

    <!-- Include the JavaScript glue code. -->
    <!-- This will load the WebAssembly module and run its main. --> 
    <script src="index.js"></script>

  </body>
</html> 

Es ist noch früh für WebAssembly, aber es gibt gute Tutorials. Und anscheinend werden wir diesen C-Code bald im Browser debuggen, so wie wir heute unser JS debuggen.

Der einzige Nachteil ist, dass nur Zahlen ausgetauscht werden können, also bedeutet das Übergeben/Rückgeben von Objekten und Strukturen derzeit das Schreiben von Konvertierungscode, aber ich bin sicher, dass es sehr bald einige generische Bibliotheksfunktionen dafür geben wird.

Ich habe tatsächlich eine minimale Menge an WebAssembly mit Rust durchgeführt. Es ist gerade jetzt ein interessantes Ökosystem. Viele Wachstumsschmerzen.
Ich suche nach einigen Bibliotheken, um die Übersetzung komplexer Datentypen zu erleichtern. Tatsächlich denke ich, dass ich später heute eine Frage stellen werde, in der ich danach frage.
Fertig. Siehe diese Frage

Es gibt Brython , mit dem Sie Python innerhalb von Webseiten verwenden können (mit etwas wie <script type="text/python">). Vorbehalte:

  1. Es erleidet eine Leistungseinbuße im Vergleich zu der gleichen Vorgehensweise in regulärem Python oder einfachem JavaScript, insbesondere zur Ladezeit der Seite.
  2. Es gibt immer noch gelegentliche Fehler.
  3. Es ist eigentlich immer noch JavaScript; Brython kompiliert einfach Ihr Python in JavaScript. Dies ist jedoch ziemlich effektiv versteckt und es ist möglich, Ihren Site-Code vollständig in Brython zu schreiben, ohne „rohes“ JavaScript zu verwenden.

Seine Vorteile:

  1. Es funktioniert ohne spezielle Browserunterstützung. Anders als die meisten anderen Transpiler kompiliert es spontan zu JavaScript. Das bedeutet, dass Sie Python-Code tatsächlich in ein <script>Tag schreiben können, anstatt Ihren Code in einem separaten Schritt in JavaScript vorkompilieren zu müssen. (Deshalb ist es jedoch langsam.)
  2. Es ist Open Source und die Entwicklung scheint ziemlich aktiv zu sein.
  3. Python ist in jeder Hinsicht besser als JavaScript.
Das sieht sehr interessant aus. Ich werde einige Zeit darin investieren; vielleicht zumindest ein Hallo-Welt-Projekt. Sie erwähnen "eine Leistungsstrafe" - haben Sie Details? Wenn nicht, profiliere ich mein Projekt kalt. Da Sie jedoch "insbesondere zum Zeitpunkt des Ladens der Seite" sagen, mildert dies meine Bedenken, da die meisten meiner SPAs aus einer Reihe von Benutzerinteraktionen bestehen, die jeweils zu etwas AJAX und der Verarbeitung des Ergebnisses führen. Es wäre gut, viel/das meiste in Python anstatt in JS codieren zu können.
@Mawg: Weitere Informationen finden Sie, wenn Sie auf der Brython-Website und/oder in der Mailingliste stöbern. Einer der größten Kosten ist, dass Brython (es sei denn, Sie versuchen, sehr schlau zu werden) beim Laden der Seite im Wesentlichen die gesamte Python-Standardbibliothek (in JavaScript-Form) laden muss. Dies ist eine beträchtliche Menge an JS-Code, der übertragen und ausgeführt werden muss. Meiner Erfahrung nach gibt es eine merkliche Verzögerung, selbst wenn eine Seite geladen wird, die Brython nur lädt, aber nicht wirklich etwas tut. Außerdem transpiliert Brython Ihren eigenen Code im Handumdrehen (dh bei jedem Laden einer Seite) in JavaScript, was ebenfalls Zeit in Anspruch nimmt.
(Fortsetzung...) Abgesehen davon habe ich eine kleine Webanwendung geschrieben, die 100 % Brython verwendet, kein "echtes" JavaScript, und es ist viel angenehmer als das Schreiben in JS. Auch die Leistung hat sich mit neueren Versionen von Brython tendenziell leicht verbessert. Ich würde vorschlagen, dass Sie herumspielen und versuchen, einige Dinge zu tun und zu sehen, ob die Leistungsprobleme etwas sind, mit dem Sie für Ihren Anwendungsfall leben können. Insgesamt ist Brython auf jeden Fall einen Blick wert.

[Ich denke, meine bestehende Antwort ist immer noch nützlich, aber ich bin auf weitere Informationen gestoßen, die mich ermutigt haben, eine weitere Antwort zu geben.]

@CAD97 und @Mawg schlagen WebAssembly als potenzielles Ziel vor, um JavaScript in Zukunft zu ersetzen. Dies ist jedoch kein Ziel des Projekts :

Versucht WebAssembly, JavaScript zu ersetzen?

Nein! WebAssembly ist als Ergänzung, nicht als Ersatz für JavaScript konzipiert. Während WebAssembly im Laufe der Zeit die Kompilierung vieler Sprachen für das Web ermöglichen wird, hat JavaScript eine unglaubliche Dynamik und wird die einzige, privilegierte (wie oben beschrieben) dynamische Sprache des Webs bleiben. Darüber hinaus wird erwartet, dass JavaScript und WebAssembly in einer Reihe von Konfigurationen zusammen verwendet werden:

  • Ganze, kompilierte C++-Apps, die JavaScript nutzen, um Dinge zusammenzufügen.
  • HTML/CSS/JavaScript-Benutzeroberfläche um einen von WebAssembly gesteuerten Hauptbereich herum, der es Entwicklern ermöglicht, die Leistungsfähigkeit von Web-Frameworks zu nutzen, um zugängliche, webnative Erfahrungen zu erstellen.
  • Größtenteils HTML/CSS/JavaScript-App mit einigen leistungsstarken WebAssembly-Modulen (z. B. Grafik, Simulation, Bild-/Ton-/Videoverarbeitung, Visualisierung, Animation, Komprimierung usw., Beispiele, die wir heute bereits in asm.js sehen können) Dadurch können Entwickler beliebte WebAssembly-Bibliotheken genauso wie heute JavaScript-Bibliotheken wiederverwenden.
  • Wenn WebAssembly die Möglichkeit erhält, auf Objekte aus der Garbage Collection zuzugreifen 🦄 , werden diese Objekte mit JavaScript geteilt und leben nicht in einer eigenen, abgeschlossenen Welt.

WebAssembly ist eine Ergänzung zu JavaScript. Der beabsichtigte Anwendungsfall besteht darin, dass Bibliotheken in WASM geschrieben und kompiliert und dann von JS aufgerufen werden. Aber angesichts der Tatsache, dass Sie JS im OP mit Python vergleichen, könnte es Sie interessieren zu wissen, dass JavaScript pythonisch wird !

Klassen

Python:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __str__(self):
        return "({x}, {y})".format(x=self.x, y=self.y)

Javascript:

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    toString() {
        return `(${this.x}, ${this.y})`;
    }
}

Unterklassen

Python:

class ColorPoint(Point):
    def __init__(self, x, y, color):
        super().__init__(x, y)
        self.color = color
    def __str__(self):
        return "{super} in color {color}".format(
            super=super().__str__(),
            color=self.color
        )

Javascript:

class ColorPoint extends Point {
    constructor(x, y, color) {
        super(x, y);
        this.color = color;
    }
    toString() {
        return `${super.toString()} in ${this.color}`;
    }
}

Diese Beispiele sprechen Ihren Schmerzpunkt der Vererbung an. Modernes JavaScript kann Klassen und Vererbung nahezu identisch mit Python ausdrücken.

Informationen zu Set-Operationen finden Sie unter Set- Objekt ( Kompatibilität ). MDN bietet grundlegende Set-Operation-Implementierungen :

Set.prototype.isSuperset = function(subset) {
    for (var elem of subset) {
        if (!this.has(elem)) {
            return false;
        }
    }
    return true;
}

Set.prototype.union = function(setB) {
    var union = new Set(this);
    for (var elem of setB) {
        union.add(elem);
    }
    return union;
}

Set.prototype.intersection = function(setB) {
    var intersection = new Set();
    for (var elem of setB) {
        if (this.has(elem)) {
            intersection.add(elem);
        }
    }
    return intersection;
}

Set.prototype.difference = function(setB) {
    var difference = new Set(this);
    for (var elem of setB) {
        difference.delete(elem);
    }
    return difference;
}

Oder alternative zerstörungsfreie Implementierungen:

Set.prototype.union = that => new Set([...this, ...that])
Set.prototype.intersection = that => new Set(this.values().filter(it => that.has(it)))
Set.prototype.difference = that => new Set(this.values().filter(it => !that.has(it)))

Sie können Operatoren nicht überladen, aber das liegt daran, dass sie Object + Objectbereits gut definiert sind (um beide Operatoren auf einen primitiven Wert und dann auf +diese Werte zu zwingen).

Ihr letzter Schmerzpunkt ist die Schwierigkeit, asynchronen JavaScript-Code zu debuggen. Leider ist das meiste davon nur, dass asynchroner Code schwer zu debuggen ist. Wenn Sie jedoch Promises und async/await verwenden , können Sie asynchronen Code schreiben, genau wie PEP 492 Coroutines mit async und await . Asynchronität ist im Allgemeinen nur schwer zu begründen, und es ist hier nicht die Schuld von JavaScript.


Der Trick, um alle Feinheiten des modernen ECMAScript nutzen zu können, besteht darin, Babel zu verwenden , um Ihre ausgefallenen, modernen Syntaxen in browserkompatibles JavaScript zu transpilieren. Wenn Sie möchten, dass eine Sprache im Web läuft, die die Website-Interaktivität unterstützt, ist JavaScript die einzige Option, zumindest bis WASM so weit ausgereift ist, dass es über GC und Objekt-Interop mit JavaScript verfügt, wodurch DOM-Methoden in WASM integriert werden können.

Meine nächste Frage ist "Babel vs. TypeScript". Aber ich werde diese Frage später stellen, nicht heute.
Bitte verlinken Sie hier, wenn Sie dies tun. Vielen Dank

Um Probleme mit verschachtelten Funktionsdefinitionen und ihren Rückrufen anzugehen, müssen Sie anfangen, den Begriff eines Javascript-Versprechens zu verwenden, was ziemlich nett ist - es eliminiert die Callback-Hölle

Javascript ES6 handhabt Set-Operationen, siehe http://2ality.com/2015/01/es6-set-operations.html