Letterlijk worden met ES6-sjabloonreeksen

Addy Osmani
Addy Osmani

Tekenreeksen in JavaScript zijn historisch gezien beperkt en missen de mogelijkheden die je zou verwachten van talen als Python of Ruby. ES6- sjabloonstrings (beschikbaar in Chrome 41+), veranderen dat fundamenteel. Ze introduceren een manier om strings te definiëren met domeinspecifieke talen (DSL's), waardoor het volgende wordt verbeterd:

  • String-interpolatie
  • Ingebedde expressies
  • Meerregelige snaren zonder hacks
  • Tekenreeksopmaak
  • String-tagging voor veilige HTML-escaping, lokalisatie en meer.

In plaats van nog een nieuwe functie in Strings te stoppen zoals we die nu kennen, introduceert Template Strings een compleet andere manier om deze problemen op te lossen.

Syntaxis

Sjabloontekenreeksen gebruiken back-ticks ( `` ) in plaats van de enkele of dubbele aanhalingstekens die we gewend zijn bij gewone tekenreeksen. Een sjabloonstring zou dus als volgt kunnen worden geschreven:

var greeting = `Yo World!`;

Tot nu toe hebben Template Strings ons niets meer opgeleverd dan normale strings. Laten we dat veranderen.

Snaarvervanging

Een van hun eerste echte voordelen is snarenvervanging. Vervanging stelt ons in staat om elke geldige JavaScript-expressie te nemen (inclusief bijvoorbeeld de toevoeging van variabelen) en binnen een Template Literal wordt het resultaat uitgevoerd als onderdeel van dezelfde string.

Sjabloontekenreeksen kunnen tijdelijke aanduidingen bevatten voor tekenreeksvervanging met behulp van de syntaxis ${ } , zoals hieronder wordt gedemonstreerd:

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

// => "Yo, Brendan!"

Omdat alle tekenreeksvervangingen in sjabloontekenreeksen JavaScript-expressies zijn, kunnen we veel meer dan alleen variabelenamen vervangen. Hieronder kunnen we bijvoorbeeld expressie-interpolatie gebruiken om in te sluiten voor wat leesbare inline wiskunde:

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.

Ze zijn ook erg handig voor functies binnen expressies:

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

De ${} werkt prima met elk type expressie, inclusief lidexpressies en methodeaanroepen:

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

Als je backticks in je string nodig hebt, kan deze als volgt worden geëscaped met het backslash-teken \ :

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

Meerdere regels

Voor tekenreeksen met meerdere regels in JavaScript zijn al enige tijd hacky-oplossingen nodig. De huidige oplossingen hiervoor vereisen dat tekenreeksen op één regel staan ​​of worden opgesplitst in tekenreeksen met meerdere regels, met behulp van een \ (backslash) vóór elke nieuwe regel. Bijvoorbeeld:

var greeting = "Yo \
World";

Hoewel dit prima zou moeten werken in de meeste moderne JavaScript-engines, is het gedrag zelf nog steeds een beetje een hack. Je kunt ook string-aaneenschakeling gebruiken om ondersteuning voor meerdere regels na te bootsen, maar dit laat ook te wensen over:

var greeting = "Yo " +
"World";

Sjabloonstrings vereenvoudigen strings met meerdere regels aanzienlijk. Voeg gewoon nieuwe regels toe waar ze nodig zijn en BOOM. Hier is een voorbeeld:

Elke witruimte binnen de backtick-syntaxis wordt ook beschouwd als onderdeel van de tekenreeks.

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

Getagde sjablonen

Tot nu toe hebben we gekeken naar het gebruik van sjabloonreeksen voor het vervangen van tekenreeksen en voor het maken van tekenreeksen met meerdere regels. Een andere krachtige functie die ze bieden, zijn getagde sjablonen. Getagde sjablonen transformeren een sjabloonreeks door een functienaam vóór de sjabloonreeks te plaatsen. Bijvoorbeeld:

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

De semantiek van een getagde sjabloonreeks verschilt sterk van die van een normale tekenreeks. In wezen zijn ze een speciaal soort functieaanroep: de bovenstaande "ontsuikert" in

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

Merk op hoe het (n + 1)-de argument overeenkomt met de vervanging die plaatsvindt tussen de n-de en (n + 1)-de vermeldingen in de stringarray. Dit kan voor allerlei zaken nuttig zijn, maar een van de meest eenvoudige is het automatisch ontsnappen van geïnterpoleerde variabelen.

U kunt bijvoorbeeld een HTML-escape-functie schrijven, zodat...

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

retourneert een tekenreeks waarin de juiste variabelen zijn vervangen, maar waarin alle HTML-onveilige tekens zijn vervangen. Laten we dat doen. Onze HTML-escape-functie heeft twee argumenten nodig: een gebruikersnaam en een opmerking. Beide kunnen onveilige HTML-tekens bevatten (namelijk ', ", <, > en &). Als de gebruikersnaam bijvoorbeeld 'Domenic Denicola' is en de opmerking '& is een leuke tag', moeten we het volgende weergeven:

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

Onze getagde sjabloonoplossing zou dus als volgt kunnen worden geschreven:

// 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"

Andere mogelijke toepassingen zijn onder meer automatisch ontsnappen, opmaak, lokalisatie en in het algemeen complexere vervangingen:

// 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}`;

Samenvatting

Sjabloonreeksen zijn aanwezig in Chrome 41 beta+, IE Tech Preview, Firefox 35+ en io.js. Als je ze vandaag de dag praktisch in productie wilt gebruiken, worden ze ondersteund in de belangrijkste ES6 Transpilers, waaronder Traceur en 6to5. Bekijk ons ​​voorbeeld van Template Strings in de Chrome-voorbeeldopslagplaats als je ze wilt uitproberen. Mogelijk bent u ook geïnteresseerd in ES6 Equivalents in ES5 , waarin wordt gedemonstreerd hoe u enkele van de verrijkende Template Strings kunt bereiken die u vandaag de dag met ES5 kunt gebruiken.

Template Strings bieden veel belangrijke mogelijkheden voor JavaScript. Deze omvatten betere manieren om string- en expressie-interpolatie uit te voeren, multiline-strings en de mogelijkheid om uw eigen DSL's te maken.

Een van de belangrijkste functies die ze bieden zijn getagde sjablonen - een cruciale functie voor het schrijven van dergelijke DSL's. Ze ontvangen de delen van een Template String als argumenten en u kunt vervolgens beslissen hoe u de strings en vervangingen gebruikt om de uiteindelijke uitvoer van uw string te bepalen.

Verder lezen