Tagged Template Literals in JavaScript

Im Blogbeitrag vor 8 Tagen mit dem Titel „Dynamische Parameter in JavaScript“ habe ich euch gezeigt, wie Funktionen mit einer variablen Anzahl von Parametern funktionieren. Heute möchte ich über die Funktion „getaggte Template“ („Tagged Template Literals“) in JavaScript sprechen, als eine Art von Funktion, die variable Anzahl von Parametern hat.

Template-Literale

Bevor wir uns dem Thema zuwenden, sollten wir zunächst über „Template Literals“ sprechen. In alten Versionen von JavaScript hätte man Folgendes getan, wenn man eine Variable zwischen statischem Text einfügen möchte:

var name = "Bernhard";
var country = "Finland";
var greet = "Hi, my name is " + name + " and I'm currently in " + country + ".";
console.log(greet);
//Hi, my name is Bernhard and I'm currently in Finland.

Mit modernem JavaScript könnt ihr „Template Literals“ verwenden, um eine Variable (oder sogar Code) in euren Strings zu platzieren, die dann interpretiert werden:

const name = "Bernhard";
const country = "Finland";
const greet = `Hi, my name is ${name} and I'm currently in ${country}.`;
console.log(greet);
//Hi, my name is Bernhard and I'm currently in Finland.

Durch die Verwendung von „Backticks“ anstelle von Anführungszeichen verwandeln wir unseren einfachen String in ein Template Literal. Ist das nicht viel einfacher zu lesen? Ah, und ja, ich bin derzeit in Finnland und nicht in Berlin. Auf den Åland-Inseln, um genau zu sein.

Tagged Template Literals

Nach dieser kurzen Einführung kommen wir nun zu den „getaggten“ Template Literals. Wenn ihr sie zum ersten Mal seht, dann kommen sie euch vielleicht ein bisschen seltsam aus. So könnte ein Beispiel aussehen:

const name = "Bernhard";
const country = "Finland";
const greet = makeItBold`Hi, my name is ${name} and I'm currently in ${country}.`;

function makeItBold(strings, ...values) {
	// strings => ['Hello, my name is ', " and I'm currently in ", '.']
	// values => ['Bernhard', 'Finland']

	let result = "";

	// Loop through the strings and values
	for (let i = 0; i < values.length; i++) {
		result += strings[i] + `<b>${values[i]}</b>`;
	}

	// Append the last string (after the last variable)
	result += strings[values.length];

	return result;
}

console.log(greet);
// Hi, my name is <b>Bernhard</b> and I'm currently in <b>Finland</b>.

Wir definieren eine Funktion(makeItBold) und schreiben dann einfach den Funktionsnamen vor das Template Literal. In der Funktion erhalten wir das „statische Strings-Array“ als ersten strings Parameter und dann eine dynamische Anzahl von Parametern für jede „Variable“ (oder genauer gesagt jeden Ausdruck) im Template Literal als zweiten values Parameter. Wir könnten diese Funktion auch so schreiben:

function makeItBold(strings, name, country) {
	// ...
}

Aber das wäre nicht wirklich flexibel, wenn wir die Variablen vertauschen oder mehr/weniger Variablen in einem anderen String haben.

Eine Möglichkeit, die Funktion etwas kürzer zu machen, ist die Verwendung von modernem JavaScript-Code, der mit Arrays arbeitet (zur besseren Lesbarkeit in mehreren Zeilen geschrieben):

function makeItBold(strings, ...values) {
	return strings.reduce(
		(result, str, i) => result + str + (values[i] ? `<b>${values[i]}</b>` : ""),
		""
	);
}

Diejenigen unter euch, die mit modernem JavaScript vertraut sind, können dies wahrscheinlich leicht lesen. Ich muss immer noch zweimal hinschauen und es sorgfältig lesen.

Ich hatte Schwierigkeiten, ein gutes „Praxisbeispiel“ zu finden, aber nachdem ich das obige Beispiel gefunden hatte, ist mir sogar eines eingefallen, das wirklich nützlich sein könnte. Es arbeitet auch nicht mit skalaren Werten, sondern mit Objekten. Was haltet ihr von diesem Beispiel?

function schema(strings, ...values) {
	return strings.reduce((result, str, i) => {
		const value = values[i];
		if (value) {
			// Check for specific schema.org types and add relevant markup
			if (value.type === "Person") {
				return (
					result +
					str +
					`<span itemscope itemtype="https://schema.org/Person">
						<span itemprop="name">${value.name}</span>
					</span>`
				);
			} else if (value.type === "Place") {
				return (
					result +
					str +
					`<span itemscope itemtype="https://schema.org/Place">
						<span itemprop="name">${value.name}</span>
					</span>`
				);
			}
		}
		return result + str;
	}, "");
}

// Usage
const name = { type: "Person", name: "Bernhard" };
const country = { type: "Place", name: "Finland" };

const greet = schema`Hello, my name is ${name} and I'm currently in ${country}.`;

console.log(greet);
// Hello, my name is <span itemscope itemtype="https://schema.org/Person"><span itemprop="name">Bernhard</span></span> and I'm currently in <span itemscope itemtype="https://schema.org/Place"><span itemprop="name">Finland</span></span>.

Fazit

Wie bereits erwähnt, war es nicht einfach, ein gutes Beispiel zu finden. Man könnte argumentieren, dass man in vielen Fällen auch einfach ein Template Literal und etwas Inline-HTML-Markup verwenden könnte. Aber trotzdem gibt es diese Funktionalität und ihr sollten wissen, wie solcher Code funktioniert.

Wenn ihr ein Beispiel mit Tagged Template Literals aus einem eurer Projekte habt, hinterlasst bitte einen Kommentar.

Veröffentlicht von

Bernhard ist fest angestellter Webentwickler, entwickelt in seiner Freizeit Plugins, schreibt in seinem Blog über WordPress und andere Themen, treibt sich gerne bei den WP Meetups in Berlin und Potsdam herum und läuft nach Feierabend den ein oder anderen Halbmarathon.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert