web-dev-qa-db-fra.com

ES6 Template Literals Vs chaînes concaténées

J'ai le code suivant pour Ecma-Script-6 template literals

let person = {name: 'John Smith'};   
let tpl = `My name is ${person.name}.`;    
let MyVar="My name is "+ person.name+".";

console.log("template literal= "+tpl);  
console.log("my variable = "+MyVar);

La sortie est la suivante:

template literal= My name is John Smith.
my variable = My name is John Smith.

this est le violon. J'ai essayé de chercher la différence exacte mais je ne l'ai pas trouvée. Ma question est la suivante: quelle est la différence entre ces deux déclarations,

  let tpl = `My name is ${person.name}.`;    

Et

  let MyVar = "My name is "+ person.name+".";

Je suis déjà capable d’obtenir la chaîne MyVar concaténée avec person.name ici, alors quel serait le scénario pour utiliser le modèle littéral?

58
Naeem Shaikh

Si vous utilisez des littéraux de modèle uniquement avec des espaces réservés (par exemple, `Hello ${person.name}`) comme dans l'exemple de la question, le résultat est identique à la concaténation de chaînes. Subjectivement, il a meilleure apparence et est plus facile à lire, en particulier pour les chaînes multilignes ou les chaînes contenant à la fois ' et " puisque vous ne devez plus échapper à ces personnages.

La lisibilité est une fonctionnalité intéressante, mais la chose la plus intéressante à propos des modèles est Littéraux de modèles étiquetés :

let person = {name: 'John Smith'}; 
let tag = (strArr, name) => strArr[0] + name.toUpperCase() + strArr[1];  
tag `My name is ${person.name}!` // Output: My name is JOHN SMITH!

Dans la troisième ligne de cet exemple, une fonction nommée tag est appelée. Le contenu de la chaîne de modèle est divisé en plusieurs variables, auxquelles vous pouvez accéder dans les arguments de la fonction tag: literal sections (dans cet exemple, la valeur de strArr[0] est My name is et la valeur de strArr[1] est !) et les substitutions (John Smith). Le littéral de modèle sera évalué par tout ce que la fonction tag retournera.

Le wiki ECMAScript répertorie certains cas d'utilisation possibles, tels que l'échappement ou la saisie automatique du codage ou la localisation. Vous pouvez créer une fonction de balise nommée msg qui recherche les parties littérales comme My name is et les remplace par des traductions dans la langue de la langue locale, par exemple en allemand:

console.log(msg`My name is ${person.name}.`) // Output: Mein Name ist John Smith.

La valeur renvoyée par la fonction tag n'a même pas besoin d'être une chaîne. Vous pouvez créer une fonction de balise nommée $ qui évalue la chaîne et l’utilise comme sélecteur de requête pour renvoyer une collection de nœuds DOM, comme dans cet exemple exemple :

$`a.${className}[href=~'//${domain}/']`
76
kapex

ES6 Propose un nouveau type de littéral de chaîne, utilisant le \ Back-tick` comme délimiteur. Ces littéraux permettent l'intégration d'expressions d'interpolation de chaînes de base, qui sont ensuite automatiquement analysées et évaluées.

let actor = {name: 'RajiniKanth', age: 68};

let oldWayStr = "<p>My name is " + actor.name + ",</p>\n" +
  "<p>I am " + actor.age + " old</p>\n";

let newWayHtmlStr =
 `<p>My name is ${actor.name},</p>
  <p>I am ${actor.age} old</p>`;

console.log(oldWayStr);
console.log(newWayHtmlStr);

Comme vous pouvez le constater, nous avons utilisé le caractère ..`` autour d'une série de caractères, interprétés comme un littéral de chaîne, mais toutes les expressions de la forme ${..} Sont analysées et évaluées immédiatement en ligne.

Un avantage vraiment intéressant des littéraux de chaîne interpolés est qu'ils sont autorisés à se diviser en plusieurs lignes:

var Actor = {"name" : "RajiniKanth"};

var text =
`Now is the time for all good men like ${Actor.name}
to come to the aid of their
country!`;
console.log( text );
// Now is the time for all good men
// to come to the aid of their
// country!

expressions interpolées

Toute expression valide est autorisée à apparaître dans ${..} Dans une chaîne interpolée lit‐ eral, Y compris les appels de fonction, les appels d'expression de fonction en ligne et même d'autres interpo‐ lated string literals!

function upper(s) {
 return s.toUpperCase();
}
var who = "reader"
var text =
`A very ${upper( "warm" )} welcome
to all of you ${upper( `${who}s` )}!`;
console.log( text );
// A very WARM welcome
// to all of you READERS!

Ici, le littéral de chaîne interpolé\\ {{who} s`` intérieur était un peu plus pratique pour nous lorsque nous combinions la variable who avec la chaîne "s", Par opposition à who + "s". Aussi, pour garder une note, un littéral de chaîne interpolé est simplement lexically scoped Où il apparaît, et non pas dynamically scoped

function foo(str) {
 var name = "foo";
 console.log( str );
}
function bar() {
 var name = "bar";
 foo( `Hello from ${name}!` );
}
var name = "global";
bar(); // "Hello from bar!"

L'utilisation de template literal Pour le code HTML est nettement plus lisible en réduisant les inconvénients.

La vieille manière simple:

'<div class="' + className + '">' +
  '<p>' + content + '</p>' +
  '<a href="' + link + '">Let\'s go</a>'
'</div>';

Avec ES6:

`<div class="${className}">
  <p>${content}</p>
  <a href="${link}">Let's go</a>
</div>`
  • Votre chaîne peut s'étendre sur plusieurs lignes.
  • Vous n'êtes pas obligé d'échapper aux caractères de citation.
  • Vous pouvez éviter des groupes tels que: ""> "
  • Vous n'êtes pas obligé d'utiliser l'opérateur plus.

Littéraux de modèles étiquetés

Nous pouvons également baliser une chaîne template. Lorsqu'une chaîne template est étiquetée, le literals et les substitutions sont passés à function qui renvoie la valeur résultante.

function myTaggedLiteral(strings) {
  console.log(strings);
}

myTaggedLiteral`test`; //["test"]

function myTaggedLiteral(strings,value,value2) {
  console.log(strings,value, value2);
}
let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5

Nous pouvons utiliser l'opérateur spread ici pour transmettre plusieurs valeurs. Le premier argument - nous l'appelons des chaînes - est un tableau de toutes les chaînes simples (le contenu entre toutes les expressions interpolées).

nous rassemblons ensuite tous les arguments suivants dans un tableau appelé valeurs à l'aide du ... gather/rest operator, bien que vous ayez bien sûr pu les laisser en tant que paramètres nommés individuels après le paramètre strings, comme nous l'avons fait ci-dessus (value1, value2 etc).

function myTaggedLiteral(strings,...values) {
  console.log(strings);
  console.log(values);    
}

let someText = 'Neat';
myTaggedLiteral`test ${someText} ${2 + 3}`;
//["test", ""]
// "Neat"
// 5

Les argument(s) rassemblés dans notre tableau de valeurs sont les résultats des expressions d'interpolation déjà évaluées trouvées dans le littéral de chaîne. Un tagged string literal Ressemble à une étape de traitement après l'évaluation des interpolations, mais avant la compilation de la valeur de chaîne finale, vous permettant ainsi de mieux contrôler la génération de la chaîne à partir du littéral. Regardons un exemple de création d'un re-usable templates.

const Actor = {
  name: "RajiniKanth",
  store: "Landmark"
}

const ActorTemplate = templater`<article>
  <h3>${'name'} is a Actor</h3>
  <p>You can find his movies at ${'store'}.</p>

</article>`;

function templater(strings, ...keys) {
  return function(data) {
  let temp = strings.slice();
  keys.forEach((key, i) => {
  temp[i] = temp[i] + data[key];
  });
  return temp.join('');
  }
};

const myTemplate = ActorTemplate(Actor);
console.log(myTemplate);

cordes brutes

nos fonctions de balises reçoivent un premier argument appelé strings, qui est un array. Mais il y a un peu de données supplémentaires incluses: les versions brutes non traitées de toutes les chaînes. Vous pouvez accéder à ces valeurs de chaîne brutes en utilisant la propriété .raw, Comme ceci:

function showraw(strings, ...values) {
 console.log( strings );
 console.log( strings.raw );
}
showraw`Hello\nWorld`;

Comme vous pouvez le constater, la version raw de la chaîne conserve la séquence\n échappée, tandis que la version traitée de la chaîne la traite comme une nouvelle ligne réelle non échappée. ES6 Est livré avec une fonction intégrée qui peut être utilisée comme une balise littérale de chaîne: String.raw(..). Il passe simplement à travers les versions brutes du strings:

console.log( `Hello\nWorld` );
/* "Hello
World" */

console.log( String.raw`Hello\nWorld` );
// "Hello\nWorld"
14
Thalaivar

C'est beaucoup plus propre et, comme indiqué dans les commentaires, est une caractéristique commune dans d'autres langues. L'autre chose que j'ai trouvée à Nice, ce sont les sauts de ligne, très utiles pour écrire des chaînes.

let person = {name: 'John Smith', age: 24, greeting: 'Cool!' };

let usualHtmlStr = "<p>My name is " + person.name + ",</p>\n" +
                   "<p>I am " + person.age + " old</p>\n" +
                   "<strong>\"" + person.greeting +"\" is what I usually say</strong>";


let newHtmlStr = 
 `<p>My name is ${person.name},</p>
  <p>I am ${person.age} old</p>
  <p>"${person.greeting}" is what I usually say</strong>`;


console.log(usualHtmlStr);
console.log(newHtmlStr);
4
Rigotti

Tandis que ma réponse ne répond pas directement à la question. J'ai pensé qu'il serait peut-être intéressant de souligner un inconvénient de l'utilisation de modèles de littéraux en faveur de la jointure de tableaux.

Disons que j'ai

let patient1 = {firstName: "John", lastName: "Smith"};
let patient2 = {firstName: "Dwayne", lastName: "Johnson", middleName: "'The Rock'"};

Donc, certains patients ont un middleName et d'autres pas.

Si je voulais une chaîne représentant le nom complet d'un patient

let patientName = `${patient1.firstName} ${patient1.middleName} ${patient1.lastName}`;

Alors ceci deviendrait "John undefined Smith"

Cependant si je le faisais

let patientName = [patient1.firstName, patient1.middleName,  patient1.lastName].join(" ");

Alors cela deviendrait juste "John Smith"

EDIT

General_Twyckenham a souligné qu'une jointure sur "" entraînerait un espace supplémentaire entre "John" et "Smith".

Pour contourner ce problème, vous pouvez avoir un filtre avant la jointure pour vous débarrasser des valeurs de fausseté: [patient1.firstName, patient1.middleName, patient1.lastName].filter(el => el).join(" ");

2
Dhruv Prakash