Literal mit ES6-Vorlagenstrings abrufen

Strings in JavaScript waren in der Vergangenheit eingeschränkt und boten nicht die Funktionen, die man von Sprachen wie Python oder Ruby erwarten würde. ES6-Vorlagenliterale (verfügbar in Chrome 41 und höher) ändern das grundlegend. Sie bieten eine Möglichkeit, Strings mit domainspezifischen Sprachen (DSLs) zu definieren, was folgende Vorteile bietet:

  • String interpolation
  • Eingebettete Ausdrücke
  • Mehrzeilige Strings ohne Hacks
  • Stringformatierung
  • String-Tagging für sicheres HTML-Escaping, Lokalisierung und mehr.

Anstatt eine weitere Funktion in die uns bekannten Strings einzufügen, bieten Template-Strings eine völlig andere Möglichkeit, diese Probleme zu lösen.

Syntax

Für Template-Strings werden Graviszeichen (``) anstelle der einfachen oder doppelten Anführungszeichen verwendet, die wir von regulären Strings kennen. Ein Vorlagenstring könnte also so aussehen:

var greeting = `Yo World!`;

Bisher haben wir mit Template-Strings nichts erreicht, was wir nicht auch mit normalen Strings hätten erreichen können. Das wollen wir ändern.

String-Substitution

Einer der ersten echten Vorteile ist die String-Substitution. Durch die Substitution können wir jeden gültigen JavaScript-Ausdruck (z. B. die Addition von Variablen) in ein Template Literal einfügen. Das Ergebnis wird dann als Teil desselben Strings ausgegeben.

Vorlagenstrings können Platzhalter für die String-Ersetzung mit der ${ }-Syntax enthalten, wie unten gezeigt:

// Simple string substitution
var name = "Brendan";
console.log(`Yo, ${name}!`);

// => "Yo, Brendan!"

Da alle String-Ersetzungen in Vorlagenstrings JavaScript-Ausdrücke sind, können wir viel mehr als nur Variablennamen ersetzen. Unten sehen Sie ein Beispiel für die Einbettung von Inline-Mathematik mithilfe der Ausdrucksinterpolation:

var a = 10;
var b = 10;
console.log(`JavaScript first appeared ${a+b} years ago. Wow!`);

//=> JavaScript first appeared 20 years ago. Wow!

console.log(`The number of JS MVC frameworks is ${2 * (a + b)} and not ${10 * (a + b)}.`);
//=> The number of JS frameworks is 40 and not 200.

Sie sind auch sehr nützlich für Funktionen in Ausdrücken:

function fn() { return "I am a result. Rarr"; }
console.log(`foo ${fn()} bar`);
//=> foo I am a result. Rarr bar.

Der Ausdruck ${} funktioniert mit jeder Art von Ausdruck, einschließlich Member-Ausdrücken und Methodenaufrufen:

var user = {name: 'Caitlin Potter'};
console.log(`Thanks for getting this into V8, ${user.name.toUpperCase()}.`);

// => "Thanks for getting this into V8, CAITLIN POTTER";

// And another example
var thing = 'template strings';
console.log(`Say hello to ${thing}.`);

// => Say hello to template strings

Wenn Sie Backticks in Ihrem String benötigen, können Sie sie mit dem umgekehrten Schrägstrich-Zeichen \ maskieren:

var greeting = `\`Yo\` World!`;

Mehrzeilige Strings

Für mehrzeilige Strings in JavaScript waren lange Zeit umständliche Workarounds erforderlich. Bei den aktuellen Lösungen müssen Strings entweder in einer einzelnen Zeile vorhanden sein oder mit einem \ (Backslash) vor jeder neuen Zeile in mehrzeilige Strings aufgeteilt werden. Beispiel:

var greeting = "Yo \
World";

Das sollte in den meisten modernen JavaScript-Engines funktionieren, aber das Verhalten selbst ist immer noch ein bisschen ein Hack. Man kann auch die Stringverkettung verwenden, um die Unterstützung mehrerer Zeilen vorzutäuschen, aber auch das lässt zu wünschen übrig:

var greeting = "Yo " +
"World";

Mit Template-Strings werden mehrzeilige Strings deutlich vereinfacht. Fügen Sie einfach Zeilenumbrüche ein, wo sie benötigt werden, und schon ist es erledigt. Beispiel:

Alle Leerzeichen innerhalb der Backtick-Syntax werden ebenfalls als Teil des Strings betrachtet.

console.log(`string text line 1
string text line 2`);

Getaggte Vorlagen

Bisher haben wir uns angesehen, wie Template-Strings für die String-Substitution und zum Erstellen von mehrzeiligen Strings verwendet werden. Eine weitere leistungsstarke Funktion sind getaggte Vorlagen. Bei Tagged Templates wird ein Vorlagenstring transformiert, indem ein Funktionsname vor den Vorlagenstring gesetzt wird. Beispiel:

fn`Hello ${you}! You're looking ${adjective} today!`

Die Semantik eines getaggten Vorlagenstrings unterscheidet sich stark von der eines normalen Vorlagenstrings. Im Grunde handelt es sich um eine spezielle Art von Funktionsaufruf: Das oben genannte wird in Folgendes umgewandelt:

fn(["Hello ", "! You're looking ", " today!"], you, adjective);

Das (n + 1)te Argument entspricht der Ersetzung, die zwischen dem n-ten und dem (n + 1)ten Eintrag im String-Array erfolgt. Das kann für viele Dinge nützlich sein, aber am einfachsten ist die automatische Maskierung aller interpolierten Variablen.

Sie könnten beispielsweise eine Funktion zum Escapen von HTML schreiben, die…

html`<p title="${title}">Hello ${you}!</p>`

Gibt einen String mit den entsprechenden Variablen zurück, wobei alle HTML-unsicheren Zeichen ersetzt werden. Lass uns das tun. Unsere HTML-Escaping-Funktion verwendet zwei Argumente: einen Nutzernamen und einen Kommentar. Beide können HTML-unsichere Zeichen enthalten (nämlich ', ", <, > und &). Wenn der Nutzername beispielsweise „Domenic Denicola“ und der Kommentar „& ist ein lustiges Tag“ lautet, sollte die Ausgabe so aussehen:

<b>Domenic Denicola says:</b> "&amp; is a fun tag"

Unsere Lösung mit getaggten Vorlagen könnte also so aussehen:

// HTML Escape helper utility
var util = (function () {
    // Thanks to Andrea Giammarchi
    var
    reEscape = /[&<>'"]/g,
    reUnescape = /&(?:amp|#38|lt|#60|gt|#62|apos|#39|quot|#34);/g,
    oEscape = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        "'": '&#39;',
        '"': '&quot;'
    },
    oUnescape = {
        '&amp;': '&',
        '&#38;': '&',
        '&lt;': '<',
        '&#60;': '<',
        '&gt;': '>',
        '&#62;': '>',
        '&apos;': "'",
        '&#39;': "'",
        '&quot;': '"',
        '&#34;': '"'
    },
    fnEscape = function (m) {
        return oEscape[m];
    },
    fnUnescape = function (m) {
        return oUnescape[m];
    },
    replace = String.prototype.replace
    ;
    return (Object.freeze || Object)({
    escape: function escape(s) {
        return replace.call(s, reEscape, fnEscape);
    },
    unescape: function unescape(s) {
        return replace.call(s, reUnescape, fnUnescape);
    }
    });
}());

// Tagged template function
function html(pieces) {
    var result = pieces[0];
    var substitutions = [].slice.call(arguments, 1);
    for (var i = 0; i < substitutions.length; ++i) {
        result += util.escape(substitutions[i]) + pieces[i + 1];
    }

    return result;
}

var username = "Domenic Denicola";
var tag = "& is a fun tag";
console.log(html`<b>${username} says</b>: "${tag}"`);
//=> <b>Domenic Denicola says</b>: "&amp; is a fun tag"

Weitere mögliche Anwendungsfälle sind das automatische Escaping, die Formatierung, die Lokalisierung und im Allgemeinen komplexere Ersetzungen:

// Contextual auto-escaping
qsa`.${className}`;
safehtml`<a href="${url}?q=${query}" onclick="alert('${message}')" style="color: ${color}">${message}</a>`;

// Localization and formatting
l10n`Hello ${name}; you are visitor number ${visitor}:n! You have ${money}:c in your account!`

// Embedded HTML/XML
jsx`<a href="${url}">${text}</a>` // becomes React.DOM.a({ href: url }, text)

// DSLs for code execution
var childProcess = sh`ps ax | grep ${pid}`;

Zusammenfassung

Vorlagenliterale sind in Chrome 41 Beta+, IE Tech Preview, Firefox 35+ und io.js verfügbar. Wenn Sie sie heute in der Produktion verwenden möchten, werden sie in wichtigen ES6-Transpilern wie Traceur und 6to5 unterstützt. Wenn Sie sie ausprobieren möchten, sehen Sie sich unser Beispiel für Vorlagenstrings im Chrome-Beispiel-Repository an. Möglicherweise interessiert Sie auch ES6 Equivalents in ES5. Dort wird gezeigt, wie Sie einige der Vorteile von Template-Strings mit ES5 nutzen können.

Template-Strings bieten viele wichtige Funktionen für JavaScript. Dazu gehören bessere Möglichkeiten für die String- und Ausdrucksinterpolation, mehrzeilige Strings und die Möglichkeit, eigene DSLs zu erstellen.

Eine der wichtigsten Funktionen, die sie bieten, sind getaggte Vorlagen, die für die Erstellung solcher DSLs unerlässlich sind. Sie erhalten die Teile eines Vorlagenstrings als Argumente. Sie können dann entscheiden, wie Sie die Strings und Ersetzungen verwenden, um die endgültige Ausgabe des Strings zu bestimmen.

Weiterführende Literatur